home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 August: Tool Chest / Dev.CD Aug 94.toast / Tool Chest / Development Platforms / Macintosh Common Lisp Related / User Contributions / qt-objects-29.lisp < prev    next >
Encoding:
Text File  |  1994-06-16  |  83.5 KB  |  2,168 lines  |  [TEXT/CCL2]

  1. ;;; this is qt-objects.lisp, version 2.9 
  2. ;;; Last changed: March 22, 1994
  3.  
  4. (in-package :cl-user)
  5.  
  6. #|
  7. This code provides an object-oriented interface to QuickTime
  8. movies.  It defines the basic classes movie and movie-view.
  9. Movie-windows, movie-windoids, and movie-dialog-items are also defined
  10. as specializations of movie-view.  Clicking on movie-dialog-items is
  11. like pressing a play-pause button.  
  12.  
  13. To use qt-objects:
  14. 1) Make sure you have the QuickTime extension installed in your Extensions folder.
  15. 2) Load this file.
  16. 3) Evaluate (movie-test) to play a movie (you must have a movie on disk).
  17.  
  18. For best performance:
  19. a.  Make sure you aren't scaling your movie.  Scaling slows down play.
  20. b.  Don't use a controller.  Use the method play-movie* to play your movie.
  21. c.  Try allocating enough Mac Heap space so that the movie will be loaded into ram (see
  22.     the function set-mac-heap-size).
  23.  
  24. ;;;                 EXAMPLES
  25. ;(please send more examples to neves@ils.nwu.edu)
  26. ;1. A simple movie window
  27. (movie-test) ; bring up a dialog to play a movie file
  28. ;2. A window with a movie view
  29. (defvar *v*)
  30. (defvar *w*)  ;create a window with a movie view
  31. (setf *w*
  32.       (make-instance 'window
  33.         :color-p t
  34.         :view-size #@(400 525) ;scales all movies to this size.
  35.         :view-subviews
  36.         (list
  37.          (setf *v*
  38.                (make-instance 'movie-view
  39.                  :view-position #@(10 10)
  40. ;                :show-controller nil ;if you don't want a controller, set to nil
  41.                  :movie
  42.                  (make-instance 'movie
  43.                    :file (choose-movie-dialog)))))))
  44. ;3. Changing a movie
  45. ;change the movie in the view
  46. ;It, unfortunately, sizes the movie to the movie view
  47. (setf (view-movie *v*) (make-instance 'movie :file (choose-movie-dialog)))
  48. ;4. Hiding/showing a movie view (if you don't already have a view hide method)
  49. ;hide movie
  50. (set-view-position *v* (add-points (view-position *v*) #@(2000 2000)))
  51. ;show movie
  52. (set-view-position *v* (subtract-points (view-position *v*) #@(2000 2000)))
  53. ;5. Play a movie with play-movie* (if you don't have a controller)
  54. (play-movie* (view-movie *v*))
  55. ;;;                END EXAMPLES
  56.  
  57. Please send comments or improvements to neves@ils.nwu.edu
  58.  
  59. Authors:
  60. Kemi Jona (jona@ils.nwu.edu)
  61. Mike Korcuska (korcuska@ils.nwu.edu)
  62. Jeff Lind (lind@ils.nwu.edu)
  63. David Neves (neves@ils.nwu.edu)
  64.  
  65. The Institute for the Learning Sciences
  66. Northwestern Unversity
  67. 1890 Maple Ave
  68. Evanston, IL 60201
  69.  
  70. - and -
  71.  
  72. Marc Davis (mdavis@media.mit.edu)
  73. Mike Travers (mt@media.mit.edu)
  74. Brian Williams (bwill@athena.mit.edu)
  75.  
  76. Media Laboratory
  77. Learning and Common Sense Group
  78. Massachusetts Institute of Technology
  79. Cambridge, MA 02139
  80.  
  81.  
  82. New features/Changes
  83. ====================
  84.   (Version 2.9)
  85. - Fixed 10k memory leak when new movies w/ controllers were created (multiple
  86.   controllers were being created for a single movie and only 1 was disposed of).  
  87.   Update-for-new-movie now checks to see if the view is within
  88.   a window (otherwise with-focused-view doesn't do anything reasonable) and
  89.   install-view-in-window on movie views is changed to an after method so that the
  90.   initialization of a movie-view gets done when it is within a window. -David 
  91. - wrap several methods in without-interrupts so that event-processing can't sneak in
  92.   and cause problems. -Jeff L, David
  93.   (Version 2.8)
  94. - add simple-view specialization for add-child-movie-views
  95.   (Version 2.7)
  96. - Code from Bill St. Clair to keep track of movie-views so that they can be correctly
  97.   positioned when their ancestor views are moved.  
  98.   Changes to Bill's code. -David
  99. - Set the minimum mac heap size in enhance-movie-playback so that movies play smoothly.
  100.   Change zero's in enhance-movie-playback to calls to get-movie-time.
  101.   Rewrite quicktime-event-hook
  102.   Quicktime-event-hook now works with combinations of controller and non controller
  103.   video views.
  104.   Removied call to #_ExitMovies in end-quicktime.  Current Apple advice is to not to call
  105.   #_ExitMovies in an application. -David
  106. - now setting *idle-sleep-ticks* to optimize playback performance - David
  107. - enhance-movie-playback now works properly - David
  108. - use set-mac-heap-size to allocate memory for your movies in RAM to
  109.   realy increase performance - David
  110. - movie-windows with controller and grow-icon now don't change movie
  111.   box size (Kemi J- thanks to David N for pointing out the bug)
  112. - handles to movies now made unpurgeable - this should help avoid crashes (Kemi J)
  113. - checks for valid handles inserted - this should eradicate alot of
  114.   crashes (Jeff L)
  115. - filespec stuff cleaned up (major thanks to Mike K). Additional notes
  116.   regarding this cleanup at end of this file
  117. - creating a movie-view without installing it in a window is now
  118.   kosher (thanks to Jeff L)
  119. - "empty" movie-views now supported - supply nil for movie-pathname,
  120.   or just don't pass movie-view a movie object (also due to Jeff L)
  121. - new function that returns the time of a movie frame or range of frames
  122.   in a human readable (SMPTE-format) string (by Kemi J)
  123. - looping and palindrome play modes now supported (Kemi J)
  124. - controller play/pause button now reflects current state of
  125.   movie after call to play-movie - you must call play-movie on the
  126.   movie-view, not on the movie itself.  See comments for play-movie
  127.   methods (also by Kemi J) - this broke in QT 1.6
  128. - slightly modified eventhook - this may prevent some crashes (?)
  129. - new variable *signal-error-if-no-quicktime* [default T].  Set to nil if
  130.   you don't want an error signalled at Lisp startup in images that are run
  131.   on machines w/ no quicktime.
  132. - code to get movie from a resource handle (Peter Stone) so movies can be stored
  133.   in the resource fork of a saved application (for example) 
  134.  
  135. Known Problems/ stuff to do:
  136. ============================
  137.  
  138. - need to figure out why the play/pause button isn't working anymore
  139. - movie-view not drawing after an add-subviews call (this should be fixed now)
  140. - make QT package and export functions
  141. - frames-per-second is a global; should be local
  142. - would be nice to have a SMPTE time-format to frame conversion
  143.   function so user can enter HH:MM:SS.FF and have the movie jump to the
  144.   frame corresponding to that time
  145. - add a movie-done-function slot to movie-views that would contain a function
  146.   to be called when movie was finished playing - check for this in eventhook?
  147. - more support for various options: drawing badge, suppressing volume/step keys, etc
  148. - handling edit menu via trap calls (e.g. #_McSetUpEditMenu)? this may eliminate 
  149.   some complexity in Lisp code but may make things more opaque to developers.
  150.  
  151. OUTLINE OF THIS FILE:
  152. =====================
  153.  
  154. SUPPORT FUNCTIONS FROM QUICKDRAW.LISP
  155.  
  156. MOVIE CLASS
  157.  
  158. ROUTINES FOR GETTING AND PLAYING MOVIES
  159.      Initializing the System
  160.      Error Routines
  161.      Movie File Routines
  162.      Loading and Unloading Movies
  163.      Saving Movies
  164.      Controlling Movie Playback
  165.      Movie Posters and Previews
  166.      Movies and Your Event Loop
  167.      Preferred Movie Settings
  168.      Enhancing Movie Playback Performance
  169.      Disabling Movies
  170.      Generating QuickDraw Pictures From Movies
  171.      Application-Defined Movie Routines
  172.  
  173. ROUTINES FOR EDITING MOVIES
  174.      Editing Movies
  175.      Low-Level Movie Editing Routines
  176.  
  177. ROUTINES THAT MODIFY MOVIE PROPERTIES
  178.      Working With Movie Spatial Characteristics
  179.      Working With Sound Volume
  180.      Working With Movie Time
  181.      Determining Movie Creation and Modification Time     
  182.      Working With Movie User Data
  183.  
  184. MOVIE VIEW CLASS
  185.      Movie View Size and Position Functions
  186.  
  187. MOVIE WINDOW MIXIN CLASSES
  188.      Editing Interface for Movie Window Mixins
  189.      Special modal-dialog call for windows containing movie-views
  190.  
  191. MOOV SCRAP HANDLER CLASS
  192.  
  193. FRAME-BASED INTERFACE TO MOVIES
  194.      Converting Between Frames and Times
  195.      Frame-Based Functions For Controlling Movie Playback
  196.      Frame-Based Functions For Movie Posters and Previews
  197.      Frame-Based Functions For Generating QuickDraw Pictures From Movies
  198.      Frame-Based Functions For Editing Movies
  199.      Frame-Based Functions For Low-Level Movie Editing
  200.      Frame-Based Functions For Working With Movie Time
  201.  
  202. TEST CODE
  203.  
  204. START QUICKTIME
  205.  
  206. |#
  207.  
  208.  
  209. ;;;-----------------------------------------------------------------------------
  210. ;;; 
  211. ;;; SUPPORT FUNCTIONS FROM QUICKDRAW.LISP
  212. ;;; 
  213. ;;;-----------------------------------------------------------------------------
  214.  
  215. (defmacro with-rectangle-arg ((var left &optional top right bottom) &body body)
  216.   "takes a rectangle, two points, or four coordinates and makes a rectangle.
  217. body is evaluated with VAR bound to that rectangle."
  218.   `(rlet ((,var :rect))
  219.      (setup-rect ,var ,left ,top ,right ,bottom)
  220.      ,@body))
  221.  
  222. (defun setup-rect (rect left top right bottom)
  223.   (cond (bottom
  224.          (setf (pref rect rect.topleft) (make-point left top))
  225.          (setf (pref rect rect.bottomright) (make-point right bottom)))
  226.         (right
  227.          (error "Illegal rectangle arguments: ~s ~s ~s ~s"
  228.                 left top right bottom))
  229.         (top
  230.          (setf (pref rect rect.topleft) (make-point left nil))
  231.          (setf (pref rect rect.bottomright) (make-point top nil)))
  232.         (t (%setf-macptr rect left))))
  233.  
  234.  
  235.  
  236. ;;;-----------------------------------------------------------------------------
  237. ;;; 
  238. ;;; MOVIE CLASS
  239. ;;; 
  240. ;;;-----------------------------------------------------------------------------
  241.  
  242. (defclass movie ()
  243.   ((mptr :initarg :mptr :initform nil :accessor mptr)
  244.    (file :initarg :file :initform nil :accessor file)
  245.    (file-resrefnum :accessor file-resrefnum)
  246.    (resid :accessor resid)
  247. ;   (movie-scaling :initform :adjust-view-size :accessor movie-scaling)
  248.    ))
  249.  
  250. ;;; changed by KJ.  When user hits cancel used to get error.  Now if
  251. ;;; movie-fsspec-from-user returns NIL, that means user cancelled, so
  252. ;;; call (cancel)
  253. (defmethod initialize-instance :after ((my-movie movie) &rest ignore)
  254.   (declare (ignore ignore))
  255.   (rlet ((fsSpec_p :FSSpec))
  256.     (with-slots (mptr file file-resrefnum resid) my-movie
  257.       (unless mptr
  258.         (multiple-value-bind (movie resref movie-resid)
  259.                              (cond ((null file)
  260.                                     (unless (movie-fsspec-from-user fsSpec_p :preview t)
  261.                                       (cancel))
  262.                                     (get-movie-from-fsspec fsSpec_p))
  263.                                    ((probe-file file)
  264.                                     (movie-fsspec-from-path fsSpec_p file)
  265.                                     (get-movie-from-fsspec fsSpec_p))
  266.                                    (t
  267.                                     (new-movie-fsspec fsSpec_p)
  268.                                     (create-movie-file-from-fsspec fsSpec_p)))
  269.           (handle-set-unpurgeable movie)
  270.           (setf mptr movie)
  271.           (setf file (path-from-movie-fsspec fsSpec_p))
  272.           (setf file-resrefnum resref)
  273.           (setf resid movie-resid))))))
  274.  
  275. ;;; for some reason non-handles were being passed in here and causing
  276. ;;; an error, so now just by bypass the error message and only let
  277. ;;; real handles thru to the code that matters
  278. (defun handle-set-unpurgeable (handle)
  279.   (unless (handlep handle)
  280.     (error "~S is not a valid handle" handle))
  281.   (let (err)
  282.     (#_HNoPurge handle)
  283.     (setq err (#_MemError))
  284.     (unless (zerop err) (error "HNoPurge: ~S -> ~S" handle err))))
  285.  
  286. (defun handle-set-purgeable (handle)
  287.   ;(unless (handlep handle)
  288.    ; (error "~S is not a valid handle" handle))
  289.   (when (handlep handle)
  290.     (let (err)
  291.       (#_HPurge handle)
  292.       (setq err (#_MemError))
  293.       (unless (zerop err) (error "HPurge: ~S -> ~S" handle err)))))
  294.  
  295. ;;;-----------------------------------------------------------------------------
  296. ;;; 
  297. ;;; ROUTINES FOR GETTING AND PLAYING MOVIES
  298. ;;; 
  299. ;;;-----------------------------------------------------------------------------
  300.  
  301.  
  302. ;;;-----------------------------------------------------------------------------
  303. ;;; 
  304. ;;; Initializing the System
  305. ;;; 
  306. ;;;-----------------------------------------------------------------------------
  307.  
  308. (defparameter *movie-update-time-slice* 1000)   
  309. ;This parameter is measured in QuickTime units
  310.  
  311. (defparameter *movie-task-interval* 1) 
  312. ;This parameter is measured in clock ticks
  313.  
  314. (defparameter *qt-views* nil)     
  315. ;The idea here is to keep a list of all views with movie objects to make updating more efficient.
  316.  
  317.  
  318. ;;; Hook
  319.  
  320. ;;; IFT will add methods for this
  321. (defmethod ccl::editing-dialogs-p ((w t))
  322.   nil)
  323.  
  324. ;;; Eventhook
  325. (defun quicktime-eventhook ()
  326.   (dolist (view *qt-views* nil) ;return nil if couldn't handle the event
  327.     (when (view-movie view)
  328.       (if (show-controller-p view)
  329.         (when (and (view-movie-controller view) 
  330.                    (not (ccl::editing-dialogs-p view))
  331.                    (not (zerop (#_MCIsPlayerEvent (view-movie-controller view) *current-event*))))
  332.           (return-from quicktime-eventhook t)) ;handled MCIsPlayerEvent, return T
  333.         (#_MoviesTask (slot-value (view-movie view) 'mptr) 0)))))
  334.  
  335. ;;; Initialization
  336. (defvar *qt-initialized?* nil)
  337. (defvar *signal-error-if-no-quicktime* t
  338.   "Whether to signal an error if Quicktime is not installed on startup.")
  339.   
  340. (defun quicktime-installed? ()
  341.   (rlet ((response :pointer))
  342.     (zerop (#_Gestalt #$gestaltQuickTime response))))
  343.  
  344. (defun start-quicktime ()
  345.   (unless *qt-initialized?*
  346.     (if (quicktime-installed?)
  347.       (progn
  348.         (#_EnterMovies)
  349.         (push #'quicktime-eventhook *eventhook*)
  350.         (setq *IDLE-SLEEP-TICKS* 0)
  351.         (setf *qt-initialized?* t))
  352.       (when *signal-error-if-no-quicktime*
  353.         (error "QuickTime not installed!")))))
  354.  
  355. (defun end-quicktime ()
  356.   (when *qt-initialized?*
  357.     (setf *eventhook* (delete 'quicktime-eventhook *eventhook* :key 'function-name))
  358.     (setq *IDLE-SLEEP-TICKS* 5)
  359.     (dolist (mv *qt-views*)
  360.       (dispose-current-movie mv))
  361. ;    (#_ExitMovies)
  362.     (setf *qt-initialized?* nil)))
  363.  
  364. (defun initialize-quicktime ()
  365.   (start-quicktime)
  366.   (unless (member 'start-quicktime *lisp-startup-functions*)
  367.     (setf *lisp-startup-functions*
  368.           (nconc *lisp-startup-functions* (list 'start-quicktime)))
  369.     (pushnew 'end-quicktime *lisp-cleanup-functions*)))
  370.  
  371.  
  372. ;;;-----------------------------------------------------------------------------
  373. ;;; 
  374. ;;; Error Routines
  375. ;;; 
  376. ;;;-----------------------------------------------------------------------------
  377.  
  378. (defmacro errcheck-movie (form)
  379.   `(let ((result ,form)
  380.          (error (#_GetMoviesError)))
  381.      (assert (zerop error) () "~&~A had an error: ~A" ',(car form) error)
  382.      result))
  383.  
  384.  
  385. ;;;-----------------------------------------------------------------------------
  386. ;;; 
  387. ;;; Movie File Routines
  388. ;;; 
  389. ;;;-----------------------------------------------------------------------------
  390.  
  391. (defmethod open-movie-file ((my-movie movie))
  392.   (with-slots (mptr file file-resrefnum)
  393.               my-movie
  394.     (if file-resrefnum
  395.       file-resrefnum 
  396.       (rlet ((fsSpec_p :FSSpec)
  397.              (resRefNum_p :integer))
  398.         (movie-fsspec-from-path fsSpec_p file)
  399.         (#_OpenMovieFile fsSpec_p resRefNum_p #$fsWrPerm)
  400.         (setf file-resrefnum
  401.               (%get-word resRefNum_p))))))
  402.  
  403. (defun create-movie-file (&optional path)
  404.   (let ((new-movie-filename (or path (new-movie-path))))
  405.     (rlet ((fsSpec_p :FSSpec))
  406.       (movie-fsspec-from-path fsSpec_p new-movie-filename t)
  407.       (create-movie-file-from-fsspec fsSpec_p))))
  408.  
  409. (defun create-movie-file-from-fsspec (fsSpec_p)
  410.   (rlet ((ResRefNum_p :word) 
  411.          (mptr_p :pointer))
  412.     (unless (valid-fsspec-p fsspec_p) (error "Invalid file specification."))
  413.     (errcheck-movie 
  414.      (#_CreateMovieFile fsSpec_p #$MovieFileType 0 #$createmoviefileDeleteCurFile resrefnum_p mptr_p))
  415.     (values (%get-ptr mptr_p) 
  416.             (%get-signed-word resrefnum_p)
  417.             (rref mptr_p :resourcespec.resid))))
  418.  
  419. (defun get-movie-from-file (fsSpec-or-path &optional (new-movie-flags #$newMovieActive))
  420.   (if (pathnamep fsSpec-or-path)
  421.     (rlet ((fsSpec_p :FSSpec))
  422.       (movie-fsspec-from-path fsSpec_p (truename fsSpec-or-path))
  423.       (get-movie-from-fsspec fsSpec_p new-movie-flags))
  424.     (get-movie-from-fsspec fsSpec-or-path new-movie-flags)))
  425.  
  426. (defun get-movie-from-fsspec (fsSpec_p &optional (new-movie-flags #$newMovieActive)) 
  427.   (rlet ((movieResRefNum_p :word)
  428.          (mptr_p :pointer)
  429.          (actualResId_p :word))
  430.     (unless (fsspec-exists-p fsSpec_p) (error "Not a valid file specification."))
  431.     (errcheck-movie (#_OpenMovieFile fsSpec_p movieResRefNum_p #$fsRdPerm))
  432.     (setf (%get-signed-word actualResId_p) #$DoTheRightThing)
  433.     (errcheck-movie
  434.      (#_NewMovieFromFile mptr_p (%get-signed-word movieResRefnum_p)
  435.       actualResId_p (%null-ptr) new-movie-flags (%null-ptr)))
  436.     (errcheck-movie (#_CloseMovieFile (%get-signed-word movieResRefNum_p)))
  437.     (values (%get-ptr mptr_p) 
  438.             (%get-signed-word movieResRefNum_p) 
  439.             (%get-signed-word actualResId_p))))
  440.  
  441. (defun movie-fsspec-from-user (fsSpec_p &key (preview nil))
  442.   "Fill fsSpec_p and return OsError"
  443.   (rlet ((types_p (:array :OSType 1))
  444.          (reply_p :StandardFileReply))
  445.     (%put-ostype types_p :|MooV|)
  446.     (if preview
  447.       (#_StandardGetFilePreview (%null-ptr) 1 types_p reply_p)
  448.       (#_StandardGetFile (%null-ptr) 1 types_p reply_p))
  449.     (when (rref reply_p :StandardFileReply.sfGood)
  450.       (with-pstrs ((filename_p (rref reply_p :StandardFileReply.sfFile.name)))
  451.         (#_FSMakeFSSpec 
  452.          (rref reply_p :StandardFileReply.sfFile.vRefNum) 
  453.          (rref reply_p :StandardFileReply.sfFile.ParID) 
  454.          filename_p fsspec_p)))))
  455.  
  456. (defun movie-fsspec-from-user-with-preview (fsSpec_p)
  457.   (movie-fsspec-from-user fsSpec_p :preview t))
  458.  
  459. (defun movie-fsspec-from-path (fsSpec_p path &optional new-file-ok?)
  460.   (with-pstrs ((filename_p (namestring path)))
  461.     (let ((result-code (#_FSmakeFSSpec 0 0 filename_p fsspec_p)))
  462.       (if (or (zerop result-code)
  463.               (and new-file-ok? (= result-code #$fnfErr)))
  464.         fsspec_p
  465.         nil))))
  466.  
  467. (defun new-movie-fsspec (fsSpec_p)
  468.   (let ((new-movie-filename (new-movie-path)))
  469.     (movie-fsspec-from-path fsSpec_p new-movie-filename t)))
  470.  
  471. (defmethod close-movie-file ((my-movie movie))
  472.   (with-slots (file-resrefnum) my-movie
  473.     (when file-resrefnum
  474.       (#_CloseMovieFile file-resrefnum)
  475.       (setf file-resrefnum nil))))
  476.  
  477. (defun new-movie-path ()
  478.   (choose-new-file-dialog 
  479.    :prompt "Name for New Movie File..." 
  480.    :button-string "Create"))
  481.  
  482. (defun path-from-movie-fsspec (fsspec)
  483.   (%path-from-fsspec fsspec))
  484.  
  485. (defun fsspec-exists-p (fsSpec_p)
  486.   "Does the file described by fsSpec_p exist?"
  487.   (rlet ((fndrInfo_p :FInfo))
  488.     (eq 0 (#_FSpGetFInfo fsSpec_p fndrInfo_p))))
  489.  
  490. (defun valid-fsspec-p (fsSpec_p)
  491.   "Is the fsSpec_p valid.  Note that an fsSpec can be valid
  492. even if the file does not exist"
  493.   (rlet ((fndrInfo_p :FInfo))
  494.     (let ((err (#_FSpGetFInfo fsSpec_p fndrInfo_p)))
  495.       (or (zerop err) (= err #$fnfErr)))))
  496.  
  497. ;;; opens standard choose movie dialog with preview and returns
  498. ;;; pathname - useful for when you want to prompt for a movie but just
  499. ;;; keep the pathname around
  500.  
  501. (defun choose-movie-dialog ()
  502.   (rlet ((fsSpec_p :FSSpec))
  503.     (unless (movie-fsspec-from-user fsSpec_p :preview t)
  504.       (cancel))
  505.     (path-from-movie-fsspec fsSpec_p)))
  506.  
  507. #|
  508. ;;; contributed by Peter Stone (psto@cix.compulink.co.uk)
  509. ;;; Get movie from resource
  510. ;;; I removed some error checking when testing
  511.  
  512. (defun get-movie-from-resource (id &optional (new-movie-flags #$newMovieActive))
  513.   (let ((movie-fsspec (make-empty-fsspec)))
  514.     (unless movie-fsspec (error "No movie was found"))
  515.     (rlet ((movieResRefNum :word)
  516.            (mptr :pointer)
  517.            (actualResId :word))
  518.        (#_NewMovieFromHandle mptr (load-and-detach-resource "moov" id) 
  519.         new-movie-flags (%null-ptr))
  520.        (values (%get-ptr mptr) 
  521.               movie-fsspec 
  522.               (%get-signed-word movieResRefNum) 
  523.               (%get-signed-word actualResId)))))
  524.  
  525. (defun make-empty-fsspec (&optional new-file-ok?)
  526.   (with-pstrs ((filename (namestring "")))
  527.     (let* ((fsspec (make-record (:fsspec :storage :pointer)))
  528.            (result-code (#_FSmakeFSSpec 0 0 filename fsspec)))
  529.       (if (or (zerop result-code)
  530.            (and new-file-ok? (= result-code #$fnfErr)))
  531.         fsspec
  532.         nil))))
  533.  
  534. (defun load-and-detach-resource (type id)
  535.   (let* ((res (#_get1resource type id)))
  536.     (#_loadresource res)
  537.     (#_detachresource res)
  538.     res))
  539.  
  540. (make-instance 'movie-window
  541.     :movie (make-instance 'movie 
  542.              :file 1500)) ; integer = moov id
  543.  
  544. ; Add test in initialize-instance:
  545.  
  546. (defmethod initialize-instance :after ((my-movie movie) &rest ignore)
  547.   (declare (ignore ignore))
  548.   (with-slots (mptr file file-resrefnum resid) my-movie
  549.     (unless mptr
  550.       (multiple-value-bind (movie fsspec resref movie-resid)
  551.                            (cond ((integerp file)
  552.                                   (get-movie-from-resource file))
  553.                                  ((null file)
  554.                                   (get-movie-from-file
  555.                                    (movie-fsspec-from-user-with-preview)))
  556.                                  ((probe-file file)
  557.                                   (get-movie-from-file file))
  558.                                  (t
  559.                                   (create-movie-file file)))
  560.         (setf mptr movie)
  561.         (setf file (path-from-movie-fsspec fsspec))
  562.         (setf file-resrefnum resref)
  563.         (setf resid movie-resid)))))
  564. |#
  565.  
  566. ;;;-----------------------------------------------------------------------------
  567. ;;; 
  568. ;;; Loading and Unloading Movies
  569. ;;; 
  570. ;;;-----------------------------------------------------------------------------
  571.  
  572. ;;; fix by KJ.  Check mptr non-nil before disposing
  573. ;;extra fix from JL--make sure that the ptr is a handle before disposing
  574. (defmethod dispose-movie ((my-movie movie))
  575.   (without-interrupts
  576.    (with-slots (mptr) my-movie
  577.      (when (handlep mptr) 
  578.        (handle-set-purgeable mptr)
  579.        (#_DisposeMovie mptr))
  580.      (setf mptr nil))))
  581.  
  582. (defun new-movie (&optional (new-movie-file-flags 1))
  583.   (let ((new-movie (make-instance 'movie
  584.                      :mptr (#_NewMovie new-movie-file-flags))))
  585.     (setf (file-resrefnum new-movie) nil)
  586.     (setf (resid new-movie) nil)
  587.     new-movie))
  588.  
  589. (defmethod new-movie-from-file ((my-movie movie) &optional (new-movie-flags 1))
  590.   (with-slots (resid file file-resrefnum) my-movie
  591.     (open-movie-file my-movie)
  592.     (rlet ((new-mptr :pointer (mptr (new-movie)))
  593.            (resName :string)
  594.            (resId :word 0)
  595.            (dataRefWasChanged :boolean))
  596.       (#_NewMovieFromFile new-mptr file-resrefnum resId resName new-movie-flags dataRefWasChanged)
  597.       (let ((new-movie (make-instance 'movie
  598.                          :mptr (%get-ptr new-mptr)
  599.                          :file file)))
  600.         (setf (file-resrefnum new-movie) file-resrefnum)
  601.         (setf (resid new-movie) (%get-signed-word resId))
  602.         (close-movie-file my-movie)
  603.         new-movie))))
  604.  
  605.  
  606. ;;;-----------------------------------------------------------------------------
  607. ;;; 
  608. ;;; Saving Movies
  609. ;;; 
  610. ;;;-----------------------------------------------------------------------------
  611.  
  612. (defmethod add-movie-resource ((my-movie movie) &optional (fsspec-or-path (new-movie-path))
  613.                                &key (new-resid 0) (new-resname ""))
  614.   (if (pathnamep fsspec-or-path)
  615.     (rlet ((fsSpec_p :FSSpec))
  616.       (movie-fsspec-from-path fsSpec_p fsspec-or-path t)
  617.       (add-movie-resource-to-fsspec my-movie fsSpec_p :new-resid new-resid :new-resname new-resname))
  618.     (add-movie-resource-to-fsspec my-movie fsspec-or-path :new-resid new-resid :new-resname new-resname)))
  619.  
  620.  
  621. (defmethod add-movie-resource-to-fsspec ((my-movie movie) fsspec_p
  622.                                          &key (new-resid 0) (new-resname ""))
  623.   (with-slots (mptr resid file-resrefnum)
  624.               my-movie
  625.     (with-pstrs ((resName_p new-resname))
  626.       (rlet ((resrefnum_p :word)
  627.              (resId_p :word new-resid))
  628.         (#_OpenMovieFile fsspec_p resrefnum_p #$fsWrPerm)
  629.         (prog1
  630.           (#_AddMovieResource mptr (%get-word resrefnum_p) resId_p resName_p)
  631.           (when (= (%get-word resrefnum_p) file-resrefnum)
  632.             (setf resid (%get-signed-word resId_p)))
  633.           )))))
  634.  
  635. (defmethod remove-movie-resource ((my-movie movie) &optional (fsspec-or-path (file my-movie)))
  636.   (if (pathnamep fsspec-or-path)
  637.     (rlet ((fsSpec_p :FSSpec))
  638.       (movie-fsspec-from-path fsSpec_p fsspec-or-path t)
  639.       (remove-movie-resource-from-fsspec my-movie fsSpec_p))
  640.     (remove-movie-resource-from-fsspec my-movie fsspec-or-path)))
  641.  
  642. (defmethod remove-movie-resource-from-fsspec ((my-movie movie) fsSpec_p)
  643.   (with-slots (resid file-resrefnum file)
  644.               my-movie
  645.     (rlet ((resrefnum_p :word))
  646.       (#_OpenMovieFile fsSpec_p resrefnum_p #$fsWrPerm)
  647.       (prog1
  648.         (#_RemoveMovieResource (%get-word resrefnum_p) resid)
  649.         (when (= (%get-word resrefnum_p) file-resrefnum)
  650.           (setf file nil)
  651.           (setf file-resrefnum nil)
  652.           (setf resid nil))))))
  653.  
  654. (defmethod update-movie-resource ((my-movie movie) &optional (fsspec-or-path (file my-movie)))
  655.   (if (pathnamep fsspec-or-path)
  656.     (rlet ((fsSpec_p :FSSpec))
  657.       (movie-fsspec-from-path fsSpec_p fsspec-or-path t)
  658.       (update-movie-resource-fsspec my-movie fsSpec_p))
  659.     (update-movie-resource-fsspec my-movie fsspec-or-path)))
  660.  
  661. (defmethod update-movie-resource-fsspec ((my-movie movie) fsSpec_p)
  662.   (with-slots (mptr resid) 
  663.               my-movie
  664.     (rlet ((resrefnum_p :word))
  665.       (#_OpenMovieFile fsSpec_p resrefnum_p #$fsWrPerm)
  666.       (#_UpdateMovieResource mptr (%get-word resrefnum_p) resid (%null-ptr)))))
  667.  
  668. (defmethod flatten-movie ((my-movie movie) &optional (fsspec-or-path (new-movie-path)))
  669.   (if (pathnamep fsspec-or-path)
  670.     (rlet ((fsSpec_p :FSSpec))
  671.       (movie-fsspec-from-path fsSpec_p fsspec-or-path t)
  672.       (flatten-movie-fsspec my-movie fsSpec_p))
  673.     (flatten-movie-fsspec my-movie fsspec-or-path)))
  674.  
  675. (defmethod flatten-movie-fsspec ((my-movie movie) fsSpec_p)
  676.   (with-slots (mptr)
  677.               my-movie
  678.     (let ((creator #$MovieFileType)
  679.           (scriptTag #$DoTheRightThing)
  680.           (movieFlattenFlags #$flattenAddMovieToDataFork)
  681.           (createMovieFileFlags #$DoTheRightThing))
  682.       (rlet ((resId_p :word 0)
  683.              (resName_p :string))
  684.         (#_FlattenMovie mptr
  685.          movieFlattenFlags
  686.          fsSpec_p creator scriptTag 
  687.          createMovieFileFlags resId_p resName_p)))))
  688.  
  689. (defmethod save-movie ((my-movie movie) &optional (pathname (file my-movie)))
  690.   (rlet ((fsSpec_p :FSSpec))
  691.     (movie-fsspec-from-path fsSpec_p pathname t)
  692.     (open-movie-file my-movie)
  693.     (update-movie-resource-fsspec my-movie fsSpec_p)
  694.     (flatten-movie-fsspec my-movie fsSpec_p)
  695.     (close-movie-file my-movie)
  696.     (setf (file my-movie) pathname)))
  697.  
  698. (defmethod has-movie-changed ((my-movie movie))
  699.   (with-slots (mptr) my-movie
  700.     (#_HasMovieChanged mptr)))
  701.  
  702. (defmethod clear-movie-changed ((my-movie movie))
  703.   (with-slots (mptr) my-movie
  704.     (#_ClearMovieChanged mptr)))
  705.  
  706.  
  707. ;;;-----------------------------------------------------------------------------
  708. ;;; 
  709. ;;; Controlling Movie Playback
  710. ;;; 
  711. ;;;-----------------------------------------------------------------------------
  712.  
  713. (defmethod get-movie-active-segment ((my-movie movie))
  714.   (with-slots (mptr) my-movie
  715.     (rlet ((start :long)
  716.            (duration :long))
  717.       (#_getmovieactivesegment mptr start duration)
  718.       (values (%get-long start) (%get-long duration)))))
  719.  
  720. (defmethod set-movie-active-segment ((my-movie movie)
  721.                                      start-time &optional (duration 0))
  722.   (#_SetMovieActiveSegment (mptr my-movie) start-time duration))
  723.  
  724. (defmethod get-movie-rate ((my-movie movie))
  725.   (#_GetMovieRate (mptr my-movie)))
  726.  
  727. (defmethod set-movie-rate ((my-movie movie) factor)
  728.   (with-slots (mptr) my-movie
  729.     (let ((preferred-rate (#_GetMoviePreferredRate mptr)))
  730.       (#_SetMovieRate mptr (* factor preferred-rate)))))
  731.  
  732. (defmethod go-to-beginning-of-movie ((my-movie movie))
  733.     (#_GoToBeginningofMovie (mptr my-movie)))
  734.  
  735. (defmethod go-to-end-of-movie ((my-movie movie))
  736.     (#_GoToEndofMovie (mptr my-movie)))
  737.  
  738. (defmethod start-movie ((my-movie movie))
  739.   (#_StartMovie (mptr my-movie)))
  740.  
  741. ;;; Note: if the movie has a controller attached, and you want the
  742. ;;; play/pause button to be updated to reflect the current play state
  743. ;;; of the movie, you should use the play-movie and stop-movie methods
  744. ;;; that are specialized on the movie-view class instead of the
  745. ;;; methods below.
  746.  
  747. (defmethod stop-movie ((my-movie movie))
  748.   (#_StopMovie (mptr my-movie)))
  749.  
  750. (defmethod play-movie ((my-movie movie))
  751.   (with-slots (mptr) my-movie
  752.     (#_SetMovieActive mptr t)
  753.     (enhance-movie-playback my-movie :ram-load t)
  754.     (#_StartMovie mptr)))
  755.  
  756. ;;; a synchronous version of play-movie that allows specification of
  757. ;;; start and end frames, and will call a function periodically during
  758. ;;; movie playback.  Written to maximize playback performance as much
  759. ;;; as possible.  Usually used for movie-views with no controller. 
  760. ;;; The function won't return until the movie is done.
  761. ;;; Event processing is locked out and controller will not update itself
  762.  
  763. (defmethod play-movie* ((movie movie)
  764.                         &key 
  765.                         (start-frame 0)
  766.                         (end-frame (get-movie-duration-in-frames movie))
  767.                         play-hook)
  768.   (declare (type integer start-frame end-frame)
  769.            (function is-movie-done (movie) t)
  770.            (function get-movie-frame (movie) integer)
  771.            (inline is-movie-done get-movie-frame)
  772.            (optimize (speed 3) (safety 0)))
  773.   (let ((mptr (slot-value movie 'mptr)))
  774.     (unwind-protect 
  775.       (without-interrupts
  776.          (set-movie-frame movie start-frame)
  777.          (play-movie movie)
  778.          (loop
  779.            (cond
  780.             ((is-movie-done movie) 
  781.              (stop-movie movie)
  782.              (return))
  783.             ((and end-frame (>= (get-movie-frame movie) end-frame))
  784.              (stop-movie movie)
  785.              (return)))
  786.            (#_MoviesTask mptr #$doTheRIghtThing)
  787.            (when play-hook (funcall play-hook movie))))
  788.       (stop-movie movie))))
  789.  
  790. (defmethod play-movie-backwards ((my-movie movie))
  791.   (set-movie-rate my-movie -1))
  792.  
  793. (defmethod fast-forward-movie ((my-movie movie) &optional (new-rate 2))
  794.   (set-movie-rate my-movie new-rate))
  795.  
  796. (defmethod fast-rewind-movie ((my-movie movie) &optional (new-rate -2))
  797.   (set-movie-rate my-movie new-rate))
  798.  
  799. (defmethod scan-forward ((my-movie movie))
  800.   (set-movie-rate my-movie 10))
  801.  
  802. (defmethod scan-reverse ((my-movie movie))
  803.   (set-movie-rate my-movie -10))
  804.  
  805. (defmethod rewind-movie ((my-movie movie))
  806.   (with-slots (mptr) my-movie
  807.     (#_GoToBeginningOfMovie mptr)
  808.     (#_STOPMOVIE mptr)))
  809.  
  810. (defmethod wind-to-end-of-movie ((my-movie movie))
  811.   (with-slots (mptr) my-movie
  812.     (#_GotoEndOfMovie mptr)
  813.     (#_STOPMOVIE mptr)))
  814.  
  815. (defmethod set-play-mode ((m movie) mode)
  816.    (let ((mode-flag (ecase mode
  817.                       (:loop #$loopTimeBase)
  818.                       (:palindrome 2)  ;const not defined apparently
  819.                       (:normal 0))))
  820.      (#_SETTIMEBASEFLAGS (get-movie-time-base m) mode-flag)))
  821.  
  822. (defmethod get-play-mode ((m movie))
  823.    (case (#_gettimebaseflags (get-movie-time-base m))
  824.      (0 :normal)
  825.      (1 :loop)
  826.      (2 :palindrome)
  827.      (otherwise :unknown)))
  828.  
  829.  
  830. ;;;-----------------------------------------------------------------------------
  831. ;;; 
  832. ;;; Movie Posters and Previews
  833. ;;; 
  834. ;;;-----------------------------------------------------------------------------
  835.  
  836. (defmethod get-movie-poster-time ((my-movie movie))
  837.   (#_GetMoviePosterTime (mptr my-movie)))
  838.  
  839. (defmethod set-movie-poster-time ((my-movie movie) time)
  840.   (#_SetMoviePosterTime (mptr my-movie) time))
  841.  
  842. (defmethod get-movie-preview-mode ((my-movie movie))
  843.   (#_GetMoviePreviewMode (mptr my-movie)))
  844.  
  845. (defmethod set-movie-preview-mode ((my-movie movie) use-preview)
  846.   (#_SetMoviePreviewMode (mptr my-movie) use-preview))
  847.  
  848. (defmethod get-movie-preview-time ((my-movie movie))
  849.   (rlet ((preview-time :timevalue)
  850.          (preview-duration :timevalue))
  851.     (#_SetMoviePreviewTime (mptr my-movie) preview-time preview-duration)
  852.     (values (%get-signed-long preview-time)
  853.             (%get-signed-long preview-duration))))
  854.  
  855. (defmethod set-movie-preview-time ((my-movie movie) preview-time preview-duration)
  856.   (#_SetMoviePreviewTime (mptr my-movie) preview-time preview-duration))
  857.  
  858. (defmethod get-poster-box ((my-movie movie))
  859.   (rlet ((poster-box :rect))
  860.     (#_GetPosterBox (mptr my-movie) poster-box)
  861.     (values (rref poster-box :rect.top) 
  862.             (rref poster-box :rect.left) 
  863.             (rref poster-box :rect.bottom) 
  864.             (rref poster-box :rect.right))))
  865.  
  866. (defmethod set-poster-box ((my-movie movie) left &optional top right bot)
  867.   (with-rectangle-arg (r left top right bot)
  868.     (#_SetPosterBox (mptr my-movie) r)))
  869.  
  870. (defmethod play-movie-preview ((my-movie movie) &optional (callout-proc nil)
  871.                                (refcon 0))
  872.   (#_PlayMoviePreview (mptr my-movie) (or callout-proc (%null-ptr)) refcon))
  873.  
  874. (defmethod show-movie-poster ((my-movie movie))
  875.   (with-slots (mptr) my-movie
  876.     (#_SetMovieTimeValue mptr (#_GetMoviePosterTime mptr))
  877.     (#_MoviesTask mptr #$doTHeRIghtThing)))
  878.  
  879.  
  880.  
  881. ;;;-----------------------------------------------------------------------------
  882. ;;; 
  883. ;;; Movies and Your Event Loop
  884. ;;; 
  885. ;;;-----------------------------------------------------------------------------
  886.  
  887.  
  888. (defmethod is-movie-done ((my-movie movie))
  889.   (#_IsMovieDone (mptr my-movie)))
  890.  
  891. (defmethod point-in-movie ((my-movie movie) point)
  892.   (#_PtInMovie (mptr my-movie) point))
  893.  
  894. (defmethod update-movie ((my-movie movie))
  895.   (#_UpdateMovie (mptr my-movie)))
  896.  
  897.  
  898.  
  899. ;;;-----------------------------------------------------------------------------
  900. ;;; 
  901. ;;; Preferred Movie Settings
  902. ;;; 
  903. ;;;-----------------------------------------------------------------------------
  904.  
  905.  
  906. (defmethod get-movie-preferred-rate ((my-movie movie))
  907.   (#_GetMoviePreferredRate (mptr my-movie)))
  908.  
  909. (defmethod set-movie-preferred-rate ((my-movie movie) rate)
  910.   (#_SetMoviePreferredRate (mptr my-movie) rate))
  911.  
  912. (defmethod get-movie-preferred-volume ((my-movie movie))
  913.   (#_GetMoviePreferredVolume (mptr my-movie)))
  914.  
  915. (defmethod set-movie-preferred-volume ((my-movie movie) volume)
  916.   (#_SetMoviePreferredVolume (mptr my-movie) volume))
  917.  
  918.  
  919.  
  920. ;;;-----------------------------------------------------------------------------
  921. ;;; 
  922. ;;; Enhancing Movie Playback Performance
  923. ;;; 
  924. ;;;-----------------------------------------------------------------------------
  925.  
  926. #|
  927. Movies play better if there is enough Mac Heap allocated to load them into memory.  
  928. If you have movie files less than 2 meg in size you might want to allocate 
  929. 2 meg by calling set-mac-heap-size.  e.g.
  930. (set-mac-heap-size 2000000)
  931. |#
  932.  
  933. ;;; Try to set the mac heap to "size".  Useful so that one can specify the amount
  934. ;;; of Mac Heap space is available for loading movies
  935. (defun set-mac-heap-size (size)
  936.     (let (p)
  937.       (when (> size (#_freemem))
  938.         (setq p (#_newptr 
  939.                           :d0 size
  940.                           :a0))
  941.         (if (%null-ptr-p p) nil (#_disposptr p)))))
  942.  
  943. (defmethod get-movie-data-size ((my-movie movie) 
  944.                                 &optional (starttime 0) (duration (get-movie-duration my-movie)))
  945.   (#_getmoviedatasize (mptr my-movie) starttime duration))
  946.  
  947. (defmethod can-load-movie-into-ram-p ((my-movie movie))
  948.   (> (#_freemem) (get-movie-data-size my-movie)))
  949.  
  950. (defconstant keepInRam 1)
  951. (defconstant unkeepInRam 2)
  952.  
  953. ;;; minimum mac heap space needed for movies not in ram to play smoothly.
  954. ;;; As a movie is playing it grabs mac heap space.  If there isn't enough it grabs some Lisp
  955. ;;; heap space which can be time consuming.
  956. ;;; Pick a number, any number :-)
  957. (defvar *min-mac-heap-size* 260000)
  958.  
  959. (defmethod enhance-movie-playback ((my-movie movie) &key (ram-load t))
  960.   (set-mac-heap-size *min-mac-heap-size*)
  961.   (with-slots (mptr) my-movie
  962.     (let ((preferred-rate (#_GetMoviePreferredRate mptr))
  963.           (movie-time (get-movie-time my-movie)))
  964.       (cond (ram-load
  965.             (when (can-load-movie-into-ram-p my-movie)
  966.               (#_LoadMovieIntoRAM mptr movie-time (get-movie-duration my-movie) keepInRam))
  967.             (#_PrerollMovie Mptr movie-time preferred-rate)) ;preroll not needed for controllers
  968.             (t
  969.              (#_PrerollMovie mptr movie-time preferred-rate))))))
  970.  
  971. ;;;-----------------------------------------------------------------------------
  972. ;;; 
  973. ;;; Disabling Movies
  974. ;;; 
  975. ;;;-----------------------------------------------------------------------------
  976.  
  977. (defmethod get-movie-active ((my-movie movie))
  978.   (#_getmovieactive (mptr my-movie)))
  979.  
  980. (defmethod set-movie-active ((my-movie movie) &optional (active t))
  981.   (#_setmovieactive (mptr my-movie) active))
  982.  
  983.  
  984. ;;;-----------------------------------------------------------------------------
  985. ;;; 
  986. ;;; Generating QuickDraw Pictures From Movies
  987. ;;; 
  988. ;;;-----------------------------------------------------------------------------
  989.  
  990. (defmethod get-movie-pict ((my-movie movie) time)
  991.   (#_GetMoviePict (mptr my-movie) time))
  992.  
  993. (defmethod get-movie-poster-pict ((my-movie movie))
  994.   (#_GetMoviePosterPict (mptr my-movie)))
  995.  
  996. ;;; a hint:  Use Mike Engber's oodles-of-utils PICT-SVM class in
  997. ;;; conjunction with the above calls to display PICTs from movies
  998. ;;; For example:
  999. ;;; (make-instance 'pict-svm :pict-handle (get-movie-poster-pict <movie>))
  1000.  
  1001. ;;; util added by KJ 1/21/93
  1002. ;;; given a variable name and a filename, creates a temporary movie
  1003. ;;; object, executes user's forms, then disposes of the movie. 
  1004.  
  1005. (defmacro with-temp-movie ((var file) &body body)
  1006.   (let ((temp (gensym)))
  1007.     `(let ((,temp (make-instance 'movie :file ,file)))
  1008.        (unwind-protect 
  1009.          (let ((,var ,temp))
  1010.            ,@body)
  1011.          (dispose-movie ,temp)))))
  1012.  
  1013. #| example using above to display a pict of the movie poster
  1014.  
  1015. (oou::oou-dependencies :pict-di)
  1016.  
  1017. (with-temp-movie (movie (choose-file-dialog :mac-file-type :|MooV|))
  1018.   (make-instance 'dialog
  1019.     :window-title "WITH-TEMP-MOVIE Demo"
  1020.     :view-subviews (list (make-instance 'pict-di 
  1021.                            :pict-handle (get-movie-poster-pict movie)))))
  1022. |#
  1023.  
  1024. ;;;-----------------------------------------------------------------------------
  1025. ;;; 
  1026. ;;; Application-Defined Movie Routines
  1027. ;;; 
  1028. ;;;-----------------------------------------------------------------------------
  1029.  
  1030. (defmethod set-movie-progress-proc ((my-movie movie) proc refcon)
  1031.   (#_SetMovieProgressProc (mptr my-movie) proc refcon))
  1032.  
  1033. (defmethod set-movie-cover-procs ((my-movie movie) uncover-proc cover-proc refcon)
  1034.   (#_SetMovieCoverProcs (mptr my-movie) uncover-proc cover-proc refcon))
  1035.  
  1036.  
  1037. ;;;-----------------------------------------------------------------------------
  1038. ;;; 
  1039. ;;; ROUTINES FOR EDITING MOVIES
  1040. ;;; 
  1041. ;;;-----------------------------------------------------------------------------
  1042.  
  1043.  
  1044. ;;;-----------------------------------------------------------------------------
  1045. ;;; 
  1046. ;;; Editing Movies
  1047. ;;; 
  1048. ;;;-----------------------------------------------------------------------------
  1049.  
  1050. (defmethod get-movie-selection ((my-movie movie))
  1051.   (with-slots (mptr)
  1052.               my-movie
  1053.     (rlet ((selectionTime :long)
  1054.            (selectionDuration :long))
  1055.       (#_GetMovieSelection
  1056.        mptr
  1057.        selectionTime
  1058.        selectionDuration)
  1059.       (values (%get-long selectionTime) (%get-long selectionDuration)))))
  1060.  
  1061. (defmethod set-movie-selection ((my-movie movie) &optional
  1062.                                 (start-time 0)
  1063.                                 (duration (get-movie-duration my-movie)))
  1064.   (with-slots (mptr) my-movie
  1065.     (#_SetMovieSelection mptr start-time duration)))
  1066.  
  1067. (defmethod add-movie-selection ((my-source-movie movie) 
  1068.                                 (my-destination-movie movie))
  1069.   (#_AddMovieSelection
  1070.    (mptr my-destination-movie)
  1071.    (mptr my-source-movie)))
  1072.  
  1073. (defmethod clear-movie-selection ((my-movie movie))
  1074.   (#_ClearMovieSelection (mptr my-movie)))
  1075.  
  1076. (defmethod cut-movie-selection ((my-movie movie))
  1077.   (#_CutMovieSelection (mptr my-movie)))
  1078.  
  1079. (defmethod copy-movie-selection ((my-movie movie))
  1080.   (#_CopyMovieSelection (mptr my-movie)))
  1081.  
  1082. (defmethod paste-movie-selection ((my-source-movie movie) 
  1083.                                   (my-destination-movie movie))
  1084.   (let ((movie-containing-selection 
  1085.          (#_copymovieselection (mptr my-source-movie))))
  1086.     (#_PasteMovieSelection
  1087.      (mptr my-destination-movie) movie-containing-selection)
  1088.     (#_disposemovie movie-containing-selection)))
  1089.  
  1090. (defmethod paste-specified-selection ((source-movie movie)
  1091.                                       source-start-time
  1092.                                       source-duration
  1093.                                       (destination-movie movie))
  1094.   (set-movie-selection source-movie
  1095.                        source-start-time
  1096.                        source-duration)
  1097.   (paste-movie-selection source-movie
  1098.                          destination-movie))
  1099.  
  1100.  
  1101. ;;;-----------------------------------------------------------------------------
  1102. ;;; 
  1103. ;;; Low-Level Movie Editing Routines
  1104. ;;; 
  1105. ;;;-----------------------------------------------------------------------------
  1106.  
  1107.  
  1108. (defmethod copy-movie-settings ((my-source-movie movie) 
  1109.                                 (my-destination-movie movie))
  1110.   (#_CopyMovieSettings 
  1111.    (mptr my-source-movie)
  1112.    (mptr my-destination-movie)))
  1113.  
  1114. (defmethod delete-movie-segment ((my-movie movie) start-time duration)
  1115.   (with-slots (mptr) my-movie
  1116.     (#_DeleteMovieSegment mptr start-time duration)))
  1117.  
  1118.  
  1119. (defmethod insert-empty-movie-segment ((my-movie movie) start-time duration)
  1120.   "Inserts empty space into a movie -- but cannot do this at the end of a movie"
  1121.   (with-slots (mptr) my-movie
  1122.     (#_InsertEmptyMovieSegment mptr start-time duration)))
  1123.  
  1124. (defmethod insert-movie-segment ((my-source-movie movie) (my-destination-movie movie) 
  1125.                                  &key 
  1126.                                  source-movie-segment-start-time
  1127.                                  source-movie-segment-duration
  1128.                                  destination-movie-insert-start-time)
  1129.   (#_InsertMovieSegment
  1130.    (mptr my-source-movie)
  1131.    (mptr my-destination-movie)
  1132.    source-movie-segment-start-time
  1133.    source-movie-segment-duration 
  1134.    destination-movie-insert-start-time))
  1135.  
  1136. (defmethod scale-movie-segment ((my-movie movie) start-time old-duration new-duration)
  1137.   (with-slots (mptr) my-movie
  1138.     (#_ScaleMovieSegment mptr start-time old-duration new-duration)))
  1139.  
  1140.  
  1141. ;;;-----------------------------------------------------------------------------
  1142. ;;; 
  1143. ;;; ROUTINES THAT MODIFY MOVIE PROPERTIES
  1144. ;;; 
  1145. ;;;-----------------------------------------------------------------------------
  1146.  
  1147.  
  1148. ;;;-----------------------------------------------------------------------------
  1149. ;;; 
  1150. ;;; Working With Movie Spatial Characteristics
  1151. ;;; 
  1152. ;;;-----------------------------------------------------------------------------
  1153.  
  1154. ;;; returns 4 values: left, top, right, bottom of movie box
  1155. (defmethod get-movie-box ((my-movie movie))
  1156.   (with-slots (mptr) my-movie
  1157.     (rlet ((movieBounds :rect))
  1158.       (#_GetMovieBox mptr movieBounds)
  1159.       (values (rref movieBounds :rect.left) 
  1160.               (rref movieBounds :rect.top) 
  1161.               (rref movieBounds :rect.right)
  1162.               (rref movieBounds :rect.bottom)))))
  1163.  
  1164. (defmethod set-movie-box ((my-movie movie) left &optional top right bottom)
  1165.   (with-rectangle-arg (r left top right bottom)
  1166.     (#_SetMovieBox (mptr my-movie) r)))
  1167.  
  1168. ;;; returns a point specifying width and height of movie box
  1169. (defmethod movie-size ((my-movie movie))
  1170.   (multiple-value-bind (left top right bottom) (get-movie-box my-movie)
  1171.     (let  ((rectwidth (- right left))
  1172.            (rectheight (- bottom top)))
  1173.       (make-point rectwidth rectheight))))
  1174.  
  1175.  
  1176. ;;;-----------------------------------------------------------------------------
  1177. ;;; 
  1178. ;;; Working With Sound Volume
  1179. ;;; 
  1180. ;;;-----------------------------------------------------------------------------
  1181.  
  1182. (defmethod get-movie-volume ((my-movie movie))
  1183.   (#_GetMovieVolume (mptr my-movie)))
  1184.  
  1185. (defmethod set-movie-volume ((my-movie movie) volume)
  1186.   (#_SetMovieVolume (mptr my-movie) volume))
  1187.  
  1188.  
  1189. ;;;-----------------------------------------------------------------------------
  1190. ;;; 
  1191. ;;; Working With Movie Time
  1192. ;;; 
  1193. ;;;-----------------------------------------------------------------------------
  1194.  
  1195. (defmethod get-movie-duration ((my-movie movie))
  1196.   (#_GetMovieDuration (mptr my-movie)))
  1197.  
  1198. (defmethod get-movie-time ((my-movie movie) &optional time-record)
  1199.   (#_GetMovieTime (mptr my-movie) (or time-record (%null-ptr))))
  1200.  
  1201. (defmethod set-movie-time ((my-movie movie) time &optional time-scale)
  1202.   (let* ((time-scale (if time-scale time-scale (get-movie-time-scale my-movie)))
  1203.          (time-record (create-time-record time time-scale)))
  1204.     (#_SetMovieTime (mptr my-movie) time-record)))
  1205.  
  1206. (defmethod get-movie-time-base ((my-movie movie))
  1207.   (#_GetMovieTimeBase (mptr my-movie)))
  1208.  
  1209. (defmethod get-movie-time-scale ((my-movie movie))
  1210.   (#_GetMovieTimeScale (mptr my-movie)))
  1211.  
  1212. (defmethod set-movie-time-scale ((my-movie movie) time-scale)
  1213.   (#_SetMovieTimeScale (mptr my-movie) time-scale))
  1214.  
  1215. (defmethod set-movie-time-value ((my-movie movie) time)
  1216.   (#_SetMovieTimeValue (mptr my-movie) time))
  1217.  
  1218.  
  1219. ;;;-----------------------------------------------------------------------------
  1220. ;;; 
  1221. ;;; Determining Movie Creation and Modification Time
  1222. ;;; 
  1223. ;;;-----------------------------------------------------------------------------
  1224.  
  1225. (defmethod get-movie-creation-time ((my-movie movie))
  1226.   (#_GetMovieCreationTime (mptr my-movie)))
  1227.  
  1228. (defmethod get-movie-modification-time ((my-movie movie))
  1229.   (#_GetMovieModificationTime (mptr my-movie)))
  1230.  
  1231.  
  1232. ;;;-----------------------------------------------------------------------------
  1233. ;;; 
  1234. ;;; Working With Movie User Data
  1235. ;;; 
  1236. ;;;-----------------------------------------------------------------------------
  1237.  
  1238. (defmethod get-movie-user-data ((my-movie movie))
  1239.   (#_GetMovieUserData (mptr my-movie)))
  1240.  
  1241.  
  1242.  
  1243.  
  1244.  
  1245. ;;;-----------------------------------------------------------------------------
  1246. ;;; 
  1247. ;;; MOVIE VIEW CLASS
  1248. ;;; 
  1249. ;;;-----------------------------------------------------------------------------
  1250.  
  1251. (defclass movie-view (simple-view)
  1252.   ((movie :initarg :movie :initform nil :accessor view-movie)
  1253.    (show-controller :initarg :show-controller :accessor show-controller-p)
  1254.    (enable-editing :initarg :enable-editing :accessor enable-editing-p)
  1255.    (controller :initform nil :accessor view-movie-controller))
  1256.   (:default-initargs :show-controller t :enable-editing nil))
  1257.  
  1258. ;;; check for quicktime before getting into trouble
  1259.  
  1260. (defmethod initialize-instance :around ((mv movie-view) &rest initargs)
  1261.   (declare (ignore initargs))
  1262.   (if (and *qt-initialized?* (quicktime-installed?))
  1263.     (call-next-method)
  1264.     (error "QuickTime is not available.  Make sure QuickTime is installed and (initialize-quicktime) has been evaluated.")))
  1265.  
  1266. (defmethod initialize-instance :after ((mv movie-view) &rest ignore)
  1267.   (declare (ignore ignore))
  1268.   (when (view-movie mv)         ;;JL--only update if there is a movie present
  1269.     (update-for-new-movie mv)))
  1270.  
  1271. #| old
  1272. (defmethod view-default-size ((mv movie-view))
  1273.   (with-slots (movie) mv
  1274.     (cond
  1275.      (movie (movie-size movie))
  1276.      (t #@(160 120))))) ;; this should perhaps change to 320x240
  1277. |#
  1278.  
  1279. (defparameter *controller-height* 16)
  1280. (defmethod view-default-size ((mv movie-view))
  1281.   (with-slots (movie) mv
  1282.     (cond
  1283.      ((and movie (show-controller-p mv))
  1284.       (add-points (movie-size movie) (make-point 0 *controller-height*)))
  1285.      (movie (movie-size movie))
  1286.      (t #@(160 120))))) ;; this should perhaps change to 320x240
  1287.  
  1288. ;;; Get a movie
  1289. ;;; can supply a pathname, a movie instance, or NIL for an "empty"
  1290. ;;; movie view
  1291. ;;; with modifications to allow a pathname to a file on the working volume only
  1292. #|
  1293.  
  1294.  Bug report - why without-interrupts is needed
  1295.  
  1296. Well, apparently when I set the view-movie from my app (not from the
  1297. listener) somehow the event manager decides to issue update events between
  1298. when the view-movie slot is set and when it is initialized. Thus, it tries
  1299. to view-draw-contents and dies because the mptr is nil. I don't know why it
  1300. should choose that time, consistently, to do it's redrawing, exactly, but
  1301. this without-interrupts fixed the problem. Go figure.
  1302. |#
  1303.  
  1304. (defmethod (setf view-movie) (pathname (view movie-view))
  1305.   (let ((log-path (if pathname (translate-logical-pathname pathname))))
  1306.     (unless (probe-file log-path)
  1307.       (error "~&Can't find file ~S" log-path))
  1308.     (without-interrupts
  1309.      (when (view-movie view)
  1310.        (dispose-current-movie view))
  1311.      (setf (slot-value view 'movie)
  1312.            (make-instance 'movie :file log-path))
  1313.      (when (wptr view)
  1314.        (initialize-movie-view view))
  1315.      (update-for-new-movie view))
  1316.     (slot-value view 'movie)))
  1317.  
  1318. (defmethod (setf view-movie) ((movie movie) (view movie-view))
  1319.   (without-interrupts
  1320.    (when (view-movie view)
  1321.      (dispose-current-movie view))
  1322.    (setf (slot-value view 'movie) movie)
  1323.    (when (wptr view)
  1324.      (initialize-movie-view view))
  1325.    (update-for-new-movie view))
  1326.   movie)
  1327.  
  1328. ;; JL--if the pathname is nil, then just set the view-movie slot to
  1329. ;; nil and erase the view
  1330.  
  1331. (defmethod (setf view-movie) ((movie null) (view movie-view))
  1332.   (without-interrupts
  1333.    (when (view-movie view)
  1334.      (dispose-current-movie view))
  1335.    (setf (slot-value view 'movie) nil)
  1336.    (invalidate-view view t))
  1337.   nil)
  1338.  
  1339. ;;; dont want to clobber movie object since may want to reinstall view
  1340. ;;; at some point and want to keep around filename
  1341. ;;;without-interrupts keeps redraw events or movie-updates
  1342. ;;;from using a disposed mptr -JL
  1343.  
  1344. (defmethod dispose-current-movie ((mv movie-view))
  1345.   (with-slots (movie controller) mv
  1346.     (without-interrupts
  1347.      (when controller
  1348.        (#_DisposeMovieController controller)
  1349.        (setq controller nil))
  1350.      (when movie
  1351.        (dispose-movie movie)
  1352.        (setf movie nil)))))
  1353.  
  1354. ;;; when no controller present, handle clicks on the movie as the
  1355. ;;; controller does: double-click to start, single click to stop playing
  1356. (defmethod view-click-event-handler ((view movie-view) where)
  1357.   (declare (ignore where))
  1358.   (unless (view-movie-controller view)
  1359.     (with-slots (movie) view
  1360.       (when movie
  1361.         (cond
  1362.          ((double-click-p)
  1363.           (when (is-movie-done movie) (rewind-movie movie))
  1364.           (play-movie movie))
  1365.          (t (stop-movie movie)))))))
  1366.  
  1367.  
  1368. ;;;-----------------------------------------------------------------------------
  1369. ;;; 
  1370. ;;; Movie View Size and Position Functions
  1371. ;;; 
  1372. ;;;-----------------------------------------------------------------------------
  1373.  
  1374. ;;; ----------- Thanks to Bill St. Clair for much of this
  1375. ;;; To ensure that the movie gets moved when one of its ancestor views gets moved or removed.
  1376. ;;; Each view keeps track of any movie-views contained within it in *movie-view-table*
  1377. (defvar *movie-view-table* (make-hash-table :test 'eq))
  1378.  
  1379. ;;; Remove views from *movie-view-table* when a view or window is deleted.
  1380. ;;; Replacement for weak hash tables below. -neves
  1381. (defmethod remove-view-from-window :before ((view movie-view))
  1382.   (map-view-ancestors view 
  1383.                       #'(lambda (ancestor)
  1384.                           (delete-movie-view-ancestor view ancestor))))
  1385.   
  1386. (defun ancestor-movie-views (ancestor)
  1387.   (gethash ancestor *movie-view-table*))
  1388.  
  1389. (defun add-movie-view-ancestor (view ancestor)
  1390.   (pushnew view (gethash ancestor *movie-view-table*)))
  1391.  
  1392. (defun delete-movie-view-ancestor (view ancestor)
  1393.   (let ((views (delete view (gethash ancestor *movie-view-table*))))
  1394.     (if views
  1395.       (setf (gethash ancestor *movie-view-table*) views)
  1396.       (remhash ancestor *movie-view-table*))))
  1397.  
  1398. (defun map-view-ancestors (view function)
  1399.   (let ((ancestor view))
  1400.     (loop
  1401.       (setq ancestor (view-container ancestor))
  1402.       (unless ancestor (return))
  1403.       (funcall function ancestor))))
  1404.  
  1405. ;in case set-view-container is used to move a tree of views.  set-view-container calls
  1406. ;remove-view-from-window so all the hash table information is destroyed.  These four methods
  1407. ;will rebuild it.
  1408. (defmethod add-child-movie-views ((view movie-view))
  1409.   (map-view-ancestors view #'(lambda (ancestor)
  1410.                                  (add-movie-view-ancestor view ancestor))))
  1411. (defmethod add-child-movie-views ((view view))
  1412.   (dovector (v (view-subviews view)) (add-child-movie-views v)))
  1413. (defmethod add-child-movie-views ((view simple-view)))
  1414. (defmethod set-view-container :after ((view view) parent)
  1415.   (declare (ignore parent))
  1416.   (add-child-movie-views view)
  1417.   )
  1418.  
  1419. (defmethod set-view-container :before ((view view) parent)
  1420.   (declare (ignore parent))
  1421.   (dolist (movie-view (gethash view *movie-view-table*))
  1422.     (map-view-ancestors view #'(lambda (ancestor)
  1423.                                  (delete-movie-view-ancestor movie-view ancestor)))))
  1424.  
  1425. (defmethod set-view-container :before ((view movie-view) parent)
  1426.   (declare (ignore parent))
  1427.   (map-view-ancestors view
  1428.                  #'(lambda (ancestor)
  1429.                      (delete-movie-view-ancestor view ancestor))))
  1430.  
  1431. (defmethod set-view-container :after ((view movie-view) parent)
  1432.   (declare (ignore parent))
  1433.   (map-view-ancestors view #'(lambda (ancestor)
  1434.                           (add-movie-view-ancestor view ancestor))))
  1435.  
  1436. (defmethod set-view-position :after (view h &optional v)
  1437.   (declare (ignore h v))
  1438.   (dolist (movie-view (ancestor-movie-views view))
  1439.     (set-movie-to-view movie-view)))
  1440. ;;; ----------- end of Bill's code
  1441.  
  1442. (defmethod set-view-position :after ((mv movie-view) h &optional v)
  1443.   (declare (ignore h v))
  1444.   (set-movie-to-view mv))
  1445.  
  1446. (defmethod set-view-size :after ((mv movie-view) h &optional v)
  1447.   (declare (ignore h v))
  1448.   (set-movie-to-view mv))
  1449.  
  1450. (defmethod set-movie-box ((movie movie) left &optional top right bot)
  1451.   (with-rectangle-arg (r left top right bot)
  1452.     (#_SetMovieBox (mptr movie) r)))
  1453.  
  1454. (defmethod set-controller-box ((movie-view movie-view) left &optional top right bot)
  1455.   (with-rectangle-arg (r left top right bot)
  1456.     (#_MCSetControllerBoundsRect (view-movie-controller movie-view) r)))
  1457.  
  1458. ;;; returns 4 values: top, left, bottom, right of movie box
  1459. (defmethod movie-box ((m movie))
  1460.   (with-slots (mptr) m
  1461.     (rlet ((movieBounds :rect))
  1462.       (#_GetMovieBox mptr movieBounds)
  1463.       (values (rref movieBounds :rect.top) (rref movieBounds :rect.left) 
  1464.               (rref movieBounds :rect.bottom) (rref movieBounds :rect.right)))))
  1465.  
  1466. ;;; returns a point specifying width and height of movie box
  1467. (defmethod movie-size ((m movie))
  1468.   (multiple-value-bind (top left bottom right) (movie-box m)
  1469.     (let  ((rectwidth (- right left))
  1470.            (rectheight (- bottom top)))
  1471.       (make-point rectwidth rectheight))))
  1472.  
  1473. (defmethod view-activate-event-handler :after ((mv movie-view))
  1474.   (when (view-movie mv)     ;;;;JL-- only activate if there is a movie in residence
  1475.     (#_SetMovieActive (slot-value (view-movie mv) 'mptr) t)
  1476.     (enhance-movie-playback (view-movie mv) :ram-load t)
  1477.     (when (view-movie-controller mv)
  1478.       (#_MCActivate (view-movie-controller mv)
  1479.        (wptr (view-window mv)) t))))
  1480.  
  1481. (defmethod view-deactivate-event-handler :after ((mv movie-view))
  1482.   ;; this will turn off background movie showing. uncomment if this is desired
  1483.   ;(#_SetMovieActive (slot-value (view-movie mv) 'mptr) nil)
  1484.   (when (view-movie-controller mv)
  1485.     (#_MCActivate (view-movie-controller mv)
  1486.      (wptr (view-window mv)) nil)))
  1487.  
  1488. (defmethod show-controller ((mv movie-view))
  1489.   (when (view-movie-controller mv)
  1490.     (#_MCSetVisible (view-movie-controller mv) t)))
  1491.  
  1492. (defmethod hide-controller ((mv movie-view))
  1493.   (when (view-movie-controller mv)
  1494.     (#_MCSetVisible (view-movie-controller mv) nil)))
  1495.  
  1496. (defmethod controller-visible-p ((mv movie-view))
  1497.   (when (view-movie-controller mv)
  1498.     (not (zerop (#_MCGetVisible (view-movie-controller mv))))))
  1499.  
  1500. ;;;JL 5/12 -- check to make sure the mptr is a valid handle
  1501. ;;;sometimes recently disposed movies are still being drawn.
  1502. ;;;this causes a crash.
  1503. (defmethod view-draw-contents :after ((movie-view movie-view))
  1504.   (with-slots (movie) movie-view
  1505.     (without-interrupts
  1506.      (when (and movie (handlep (mptr movie)))
  1507.        (with-focused-view (view-window movie-view)
  1508.          (#_SetMovieActive (slot-value movie 'mptr) t)
  1509.          (#_Updatemovie (slot-value movie 'mptr))
  1510.          (when (view-movie-controller movie-view)
  1511.            (#_MCDraw (view-movie-controller movie-view) 
  1512.             (wptr (view-window movie-view)))))))))
  1513.  
  1514. (defmethod remove-view-from-window ((mv movie-view))
  1515.   (without-interrupts
  1516.    (dispose-current-movie mv)
  1517.    (setq *qt-views* (remove mv *qt-views*)))
  1518.   (call-next-method))
  1519.  
  1520. ;;; reinstall movie if filename exists but mptr is null
  1521. ;;; this should support remove-subviews and then readding them later on.
  1522. (defmethod install-view-in-window :after ((mv movie-view) (win window))
  1523.   (initialize-movie-view mv)
  1524.   )
  1525.  
  1526. (defmethod initialize-movie-view ((mv movie-view))
  1527.   (when (view-movie mv)
  1528.     (with-slots (mptr file) (view-movie mv)
  1529.       (when (and file (null mptr))
  1530.         (multiple-value-bind (movie)
  1531.                              (get-movie-from-file file)
  1532.           (setf mptr movie))
  1533.         (update-for-new-movie mv))
  1534.       (when (and file mptr)  ;;;JL -- if the view already has a valid movie in it,
  1535.         (update-for-new-movie mv)))      ;;;then update right away
  1536.   (pushnew mv *qt-views*)))
  1537.  
  1538.  
  1539. (defmethod update-for-new-movie ((view movie-view))
  1540.   (when (wptr view)
  1541.     (with-slots (movie) view
  1542.       (let ((mptr (slot-value movie 'mptr)))
  1543.         (without-interrupts
  1544.          (with-focused-view view
  1545.            (errcheck-movie (#_SetMovieGWorld mptr (%null-ptr) (%null-ptr)))
  1546.            (when (and (show-controller-p view) (null (view-movie-controller view)))
  1547.              (with-rectangle-arg (r 0 (view-size view))
  1548.                (setf (view-movie-controller view)
  1549.                      (errcheck-movie (#_NewMovieController mptr r 
  1550.                                       (controller-creation-flags-value)))) ;#$mcTopLeftMovie
  1551.                (when (enable-editing-p view)
  1552.                  (#_MCEnableEditing (view-movie-controller view) t))
  1553.                ))) ;end with-focused-view
  1554.          (set-movie-to-view view)
  1555.          (invalidate-view view)
  1556.          (#_StopMovie mptr)
  1557.          (#_GoToBeginningOfMovie mptr)
  1558.          (with-focused-view (view-window view)
  1559.            (#_UpdateMovie mptr)) ;MK
  1560.          (#_MoviesTask mptr #$doTHeRIghtThing))))))
  1561.  
  1562. (defparameter *controller-creation-flags* (list #$mcTopLeftMovie))
  1563.  
  1564. (defun controller-creation-flags-value ()
  1565.   (let ((result 0))
  1566.     (dolist (flag *controller-creation-flags* result)
  1567.       (setq result (boole boole-ior result flag)))))
  1568.  
  1569. ;;; move the movie controller to the specified location
  1570. ;;; the trick to doing this is to unattach the movie controller,
  1571. ;;; however once this is done you must update the movie box manually
  1572. ;;; when changing sizes
  1573.  
  1574. (defmethod position-controller ((mv movie-view) top left bottom right)
  1575.   (with-slots (movie controller) mv
  1576.     (#_MCSetcontrollerAttached controller nil)
  1577.     (rlet ((movieBounds :rect)
  1578.            (mcBounds :rect
  1579.                      :top top
  1580.                      :left left
  1581.                      :bottom bottom
  1582.                      :right right))
  1583.       (#_GetMovieBox (slot-value movie 'mptr) movieBounds)
  1584.       (#_MCPositionController controller moviebounds mcbounds #$mcWithFrame))))
  1585.  
  1586. ;;; if you want the play/pause button on the controller to reflect real play state of
  1587. ;;; movie you need to use the following two methods instead of calling
  1588. ;;; the same methods directly on the movie object (so we can access
  1589. ;;; the controller)
  1590. ;;; these no longer seem to be working in QT 1.6 - don't know why
  1591.  
  1592. (defmethod play-movie ((movie-view movie-view))
  1593.   (play-movie (view-movie movie-view))
  1594.   (when (view-movie-controller movie-view)
  1595.     (#_McDoAction (view-movie-controller movie-view)
  1596.      #$mcActionPlay (%null-ptr))))
  1597.  
  1598. (defmethod stop-movie ((movie-view movie-view))
  1599.   (#_StopMovie (mptr (view-movie movie-view)))
  1600.   (when (view-movie-controller movie-view)
  1601.     (#_McDoAction (view-movie-controller movie-view)
  1602.      #$mcActionPlay (%null-ptr))))
  1603.  
  1604. ;;;-----------------------------------------------------------------------------
  1605. ;;; 
  1606. ;;; MOVIE WINDOW MIXIN CLASSES
  1607. ;;; 
  1608. ;;;-----------------------------------------------------------------------------
  1609.  
  1610. ;;; this is necessary because windoid defines a view-default-size method. 
  1611. ;;; hide window until after initialize-instance to hide ugly intermediate
  1612. ;;; drawing stages
  1613. (defclass movie-window-mixin ()
  1614.   ((last-edit :initform nil :accessor last-edit))
  1615.   (:default-initargs :enable-editing t :window-show nil))
  1616.  
  1617. (defmethod initialize-instance :after ((mw movie-window-mixin) &rest ignore)
  1618.   (declare (ignore ignore))
  1619.   (when (and (string-equal (window-title mw) "Untitled")
  1620.              (view-movie mw))
  1621.     (set-window-title mw (pathname-name (file (view-movie mw)))))
  1622.   (initialize-movie-view mw)
  1623.   (window-select mw))
  1624.  
  1625. ;;; for some reason the controller and the grow-icon don't line up
  1626. ;;; it appears that the MCL grow icon is one pixel lower than the one
  1627. ;;; in Movie Player window's.  Make default to no grow-icon - you can
  1628. ;;; have one if you want by specifying the initarg.
  1629.  
  1630. (defclass movie-window (movie-window-mixin movie-view window) ()
  1631.   (:default-initargs :grow-icon-p nil))
  1632.  
  1633. (defclass movie-windoid (movie-window-mixin movie-view windoid) ())
  1634.  
  1635. (defmethod find-movie-windoid ((movie movie))
  1636.   (find movie (windows :class 'movie-windoid :include-windoids t)
  1637.         :key #'(lambda (x)
  1638.                  (let ((mdi (car (subviews x 'movie-dialog-item))))
  1639.                    (when mdi (slot-value mdi 'movie))))))
  1640.  
  1641. (defclass movie-dialog-item (movie-view dialog-item) ()
  1642.   (:default-initargs
  1643.     :dialog-item-action #'(lambda (mdi)
  1644.                             (let ((movie (slot-value mdi 'movie)))
  1645.                               (if (command-key-p)
  1646.                                 (print (slot-value movie 'file))
  1647.                                 (cond ((is-movie-done movie)
  1648.                                        (rewind-movie movie)
  1649.                                        (play-movie movie))
  1650.                                       ((and (not (zerop (get-movie-rate movie)))
  1651.                                             (get-movie-active movie) 
  1652.                                             (not (is-movie-done movie)))
  1653.                                        (stop-movie movie))
  1654.                                       (t
  1655.                                        (play-movie movie))))))))
  1656.  
  1657. (defun standard-position (window-type)
  1658.   (cond ((equal window-type 'movie-windoid)
  1659.          #@(100 100))
  1660.         (t
  1661.          #@(40 40))))
  1662.  
  1663. (defmethod stagger-windows (window-type)
  1664.   (let ((current-windows (windows :class window-type :include-windoids t)))
  1665.     (if current-windows
  1666.       (add-points (standard-position window-type)
  1667.                   (make-point (* (length current-windows)
  1668.                                  15)
  1669.                               (* (length current-windows)
  1670.                                  15)))
  1671.       (standard-position window-type))))
  1672.  
  1673. (defmethod set-movie-to-view ((mv movie-view))
  1674.   (when (view-movie mv)
  1675. ;    (if (eq (movie-scaling mv) :adjust-view-size)
  1676.       (let* ((topleft (subtract-points #@(0 0) (view-origin mv)))
  1677.              (bottomright (add-points topleft (view-size mv))))
  1678.         (when (< (max (abs (point-h topleft)) (abs (point-v topleft) )
  1679.                            (abs (point-h bottomright)) (abs (point-v bottomright))) 30000)
  1680.           (if (view-movie-controller mv)
  1681.             (set-controller-box mv topleft bottomright)
  1682.             (set-movie-box (view-movie mv) topleft bottomright))))))
  1683. ;  )
  1684.  
  1685. ;;; a specialized version for movie windows with grow boxes and
  1686. ;;; controllers- makes sure the grow box isn't clobbered
  1687. (defmethod set-movie-to-view ((mw movie-window))
  1688.   (cond
  1689.    ;; grow box, movie, and controller?
  1690.    ((and (ccl::window-grow-icon-p mw)
  1691.          (view-movie mw)
  1692.          (view-movie-controller mw))
  1693.     (position-controller
  1694.      mw
  1695.      (rref (ccl::grow-icon-rect mw) :rect.top)
  1696.      0 ;left
  1697.      (rref (ccl::grow-icon-rect mw) :rect.bottom)
  1698.      (rref (ccl::grow-icon-rect mw) :rect.left))
  1699.     (let* ((topleft (subtract-points #@(0 0) (view-origin mw)))
  1700.            (bottomright (make-point (point-h (view-size mw))
  1701.                                     (1- (rref (ccl::grow-icon-rect mw) :rect.top)))))
  1702.       (set-movie-box (view-movie mw) topleft bottomright)))
  1703.    ;; otherwise use the standard method for movie views
  1704.    (t (call-next-method))))
  1705.  
  1706. ;;; this sometimes doesn't draw the controller when zooming up although
  1707. ;;; it does draw it when zooming back to normal size.  Why?
  1708. (defmethod window-zoom-event-handler :after ((mw movie-window) message)
  1709.   (declare (ignore message))
  1710.   (set-movie-to-view mw))
  1711.  
  1712. ;;;-----------------------------------------------------------------------------
  1713. ;;; 
  1714. ;;; Editing Interface for Movie Window Mixins
  1715. ;;; 
  1716. ;;;-----------------------------------------------------------------------------
  1717.  
  1718. ;;; Window methods for cutting/pasting.  I'm not sure how to do this if there
  1719. ;;; are multiple movie-views in a window, hence these methods are defined only
  1720. ;;; for movie-windows.
  1721.  
  1722. (defmethod copy ((w movie-window-mixin))
  1723.   (when (view-movie-controller w)
  1724.     (put-scrap :|moov| (#_MCCopy (view-movie-controller w)))))
  1725.  
  1726. (defmethod paste ((w movie-window-mixin))
  1727.   (when (view-movie-controller w)
  1728.     (#_MCPaste (view-movie-controller w) (get-scrap :|moov|))
  1729.     (setf (last-edit w) 'paste)))
  1730.  
  1731. (defmethod cut ((w movie-window-mixin))
  1732.   (when (view-movie-controller w)
  1733.     (put-scrap :|moov| (#_MCCut (view-movie-controller w)))
  1734.     (setf (last-edit w) 'cut)))
  1735.  
  1736. (defmethod undo ((w movie-window-mixin))
  1737.   (when (view-movie-controller w)
  1738.     (#_MCUndo (view-movie-controller w))
  1739.     (setf (last-edit w) 'undo)))
  1740.  
  1741. (defmethod clear ((w movie-window-mixin))
  1742.   (when (view-movie-controller w)
  1743.     (#_MCClear (view-movie-controller w))
  1744.     (setf (last-edit w) 'clear)))
  1745.  
  1746. (defmethod select-all ((w movie-window-mixin))
  1747.   (when (view-movie-controller w)
  1748.     (set-movie-selection (view-movie w))
  1749.     (#_MCDraw (view-movie-controller w) (wptr w))))
  1750.  
  1751. (defmethod window-can-do-operation ((w movie-window-mixin) operation &optional menu-item)
  1752.   (declare (ignore menu-item))
  1753.   (and (view-movie-controller w)
  1754.        (#_MCIsEditingEnabled (view-movie-controller w))
  1755.        (case operation
  1756.          (paste (get-scrap :|moov|))
  1757.          ((cut copy clear) 
  1758.           (multiple-value-bind (start dur) (get-movie-selection (view-movie w))
  1759.             (declare (ignore start))
  1760.             (not (zerop dur))))
  1761.          (undo (when (and (last-edit w) (member (last-edit w) '(paste cut undo clear)))
  1762.                  (set-menu-item-title (first (menu-items *edit-menu*)) 
  1763.                                       (format nil "Undo ~:(~A~)" (last-edit w)))
  1764.                  t))
  1765.          (select-all t)
  1766.          (t nil))))
  1767.  
  1768. ;;; Saving movies
  1769.  
  1770. (defmethod window-save ((mw movie-window))
  1771.   (save-movie (view-movie mw)))
  1772.  
  1773. (defmethod window-save-as ((mw movie-window))
  1774.   (let* ((old-filename (file (view-movie mw)))
  1775.          (new-filename (choose-new-file-dialog
  1776.                         :directory old-filename
  1777.                         :prompt "Save Movie AsÉ")))
  1778.     (save-movie (view-movie mw) new-filename)
  1779.     (set-window-title mw (pathname-name new-filename))))
  1780.  
  1781. ;;; QT MODAL DIALOG
  1782.  
  1783. ;;; special modal-dialog call that adds quicktime eventhook to the
  1784. ;;; modal dialog call so that the controller can be updated properly
  1785. ;;; not necessary to use this unless a modal dialog contains a qt-view
  1786. ;;; with a controller.
  1787.  
  1788. (defmethod qt-modal-dialog ((dialog window) &optional (close-on-exit t)
  1789.                             (eventhook 'quicktime-eventhook))
  1790.   (cond
  1791.    ;; if a list is supplied, make sure it contains eventhook, else add it
  1792.    ((and (consp eventhook)
  1793.          (not (member 'quicktime-eventhook eventhook
  1794.                       :key #'(lambda (item) (or (function-name item) item)))))
  1795.     (push 'quicktime-eventhook eventhook))
  1796.    ;; if an atom is supplied and its not the quicktime-eventhook,
  1797.    ;; create a list that contains the quicktime-eventhook and the
  1798.    ;; supplied eventhook
  1799.    ((and (atom eventhook)
  1800.          (neq eventhook 'quicktime-eventhook))
  1801.     (setq eventhook (list 'quicktime-eventhook eventhook))))
  1802.   (modal-dialog dialog close-on-exit eventhook))
  1803.                             
  1804.  
  1805. ;;;-----------------------------------------------------------------------------
  1806. ;;; 
  1807. ;;; MOOV SCRAP HANDLER CLASS
  1808. ;;; 
  1809. ;;;-----------------------------------------------------------------------------
  1810.  
  1811. (defclass moov-scrap-handler (scrap-handler) ())
  1812.  
  1813. (defmethod set-internal-scrap ((self moov-scrap-handler) scrap)
  1814.   (call-next-method self scrap)
  1815.   (when scrap (pushnew :|moov| *scrap-state*)))
  1816.  
  1817. (defmethod externalize-scrap ((h moov-scrap-handler))
  1818.   (let* ((moov (slot-value h 'ccl::internal-scrap)))
  1819.     (when moov
  1820.       (#_PutMovieOnScrap moov 0))))
  1821.  
  1822. (defmethod internalize-scrap ((h moov-scrap-handler))
  1823.   (let* ((moov (#_NewMovieFromScrap 0)))
  1824.     (setf (slot-value h 'ccl::internal-scrap) moov)))
  1825.  
  1826. (defmethod get-internal-scrap ((h moov-scrap-handler))
  1827.   (slot-value h 'ccl::internal-scrap))
  1828.  
  1829. (pushnew `(:|moov| . ,(make-instance 'moov-scrap-handler))
  1830.          *scrap-handler-alist*
  1831.          :test #'equal)
  1832.  
  1833.  
  1834.  
  1835.  
  1836.  
  1837. ;;;-----------------------------------------------------------------------------
  1838. ;;; 
  1839. ;;; FRAME-BASED INTERFACE TO MOVIES
  1840. ;;; 
  1841. ;;;-----------------------------------------------------------------------------
  1842.  
  1843.  
  1844.  
  1845. ;;;-----------------------------------------------------------------------------
  1846. ;;; 
  1847. ;;; Converting Between Frames and Times
  1848. ;;; 
  1849. ;;;-----------------------------------------------------------------------------
  1850.  
  1851. ;;;Conversions between *frames-per-second*, time, time-scale, and current-frame
  1852.  
  1853. ;;; current-frame       =  (floor (/ (* time *frames-per-second*) time-scale))
  1854. ;;; time                =  (floor (* current-frame time-scale) *frames-per-second*)
  1855. ;;; time-scale          =  (floor (/ time (floor (/ current-frame *frames-per-second*))))
  1856. ;;; *frames-per-second* =  (floor (/ time (* current-frame time-scale)))
  1857.  
  1858. ;To simulate dealing with video set *frames-per-second* to 30
  1859. ;To simulate dealing with film set *frames-per-second* to 24
  1860.  
  1861. (defvar *frames-per-second* 30)
  1862.  
  1863. (defun create-time-record (time time-scale)
  1864.   (make-record :TIMERECORD
  1865.                :VALUE.HI (num-to-hi64 time)
  1866.                :VALUE.LO (num-to-lo64 time)
  1867.                :SCALE time-scale
  1868.                :BASE (#_NewTimeBase)))
  1869.  
  1870. (defun num-to-hi64 (num)
  1871.   (floor num 4294967296))
  1872.  
  1873. (defun num-to-lo64 (num)
  1874.   (logand num 4294967295))
  1875.  
  1876. (defmethod frame-to-time ((my-movie movie) frame &key (frames-per-second *frames-per-second*))
  1877.   (floor (* frame (get-movie-time-scale my-movie)) frames-per-second))
  1878.  
  1879. (defmethod time-to-frame ((my-movie movie) time &key (frames-per-second *frames-per-second*))
  1880.   (floor (/ (* time frames-per-second) (get-movie-time-scale my-movie))))
  1881.  
  1882. ;;; this returns a string in H:MM:SS.FF format (H=hours, M=mins, S=secs, F=frames 0-29)
  1883. ;;; it can also be used to calculate the duration of a selection.  just pass in results of
  1884. ;;; get-movie-selection-in-frames and it return how long the selection is.  
  1885.  
  1886. (defmethod frame-to-smpte-time-string ((m movie) frame &key (frames-per-second *frames-per-second*))
  1887.   (let* ((time (frame-to-time m frame :frames-per-second frames-per-second))
  1888.          (time-scale (get-movie-time-scale m))
  1889.          (seconds (/ time time-scale))
  1890.          (secs+remainder (multiple-value-list (floor seconds)))
  1891.          (frames (time-to-frame m (* (second secs+remainder) time-scale)
  1892.                                 :frames-per-second frames-per-second))
  1893.          (second (mod (car secs+remainder) 60))
  1894.          (minute (mod (floor seconds 60) 60))
  1895.          (hour (floor seconds 3600)))
  1896.     (format nil "~D:~2,'0D:~2,'0D.~2,'0D" hour minute second frames)))
  1897.     
  1898.  
  1899. ;;;-----------------------------------------------------------------------------
  1900. ;;; 
  1901. ;;; Frame-Based Functions For Controlling Movie Playback
  1902. ;;; 
  1903. ;;;-----------------------------------------------------------------------------
  1904.  
  1905. (defmethod get-movie-active-segment-in-frames ((my-movie movie) &key (frames-per-second *frames-per-second*))
  1906.   (multiple-value-bind (start-time duration)
  1907.                        (get-movie-active-segment my-movie)
  1908.     (let* ((start-frame (time-to-frame my-movie start-time :frames-per-second frames-per-second))
  1909.            (end-frame (+ start-frame (time-to-frame duration my-movie :frames-per-second frames-per-second))))
  1910.       (values start-frame end-frame))))
  1911.   
  1912. (defmethod set-movie-active-segment-in-frames ((my-movie movie) start-frame end-frame &key (frames-per-second *frames-per-second*))
  1913.   (let* ((start-time (frame-to-time my-movie start-frame :frames-per-second frames-per-second))
  1914.          (duration (frame-to-time my-movie (- end-frame start-frame) :frames-per-second frames-per-second)))
  1915.     (set-movie-active-segment my-movie start-time duration)))
  1916.   
  1917. (defmethod frame-forward-movie ((movie movie) &optional (increment 1) &key (frames-per-second *frames-per-second*))
  1918.   (with-slots (mptr) movie
  1919.     (let* ((time-scale (#_GetMovieTimeScale mptr))
  1920.            (time 0)
  1921.            (time-record (create-time-record time time-scale)))
  1922.       (#_GetMovieTime mptr time-record)
  1923.       (let ((new-time (+ (rref time-record :timerecord.value.lo)
  1924.                          (* increment (/ time-scale frames-per-second)))))
  1925.         (rset time-record :timerecord.value.lo new-time)
  1926.         (#_SetMovieTime mptr time-record)
  1927.         (dispose-record time-record)
  1928.         new-time))))
  1929.  
  1930. (defmethod frame-reverse-movie ((movie movie) &optional (increment -1) &key (frames-per-second *frames-per-second*))
  1931.   (frame-forward-movie movie increment :frames-per-second frames-per-second))
  1932.  
  1933.  
  1934. ;;;-----------------------------------------------------------------------------
  1935. ;;; 
  1936. ;;;  Frame-Based Functions For Movie Posters and Previews
  1937. ;;; 
  1938. ;;;-----------------------------------------------------------------------------
  1939.  
  1940. (defmethod get-movie-poster-time-in-frames ((my-movie movie) &key (frames-per-second *frames-per-second*))
  1941.   (time-to-frame my-movie (get-movie-poster-time my-movie) :frames-per-second frames-per-second))
  1942.  
  1943. (defmethod set-movie-poster-time-in-frames ((my-movie movie) frame &key (frames-per-second *frames-per-second*))
  1944.   (set-movie-poster-time my-movie (frame-to-time my-movie frame :frames-per-second frames-per-second)))
  1945.  
  1946. (defmethod get-movie-preview-time-in-frames ((my-movie movie) &key (frames-per-second *frames-per-second*))
  1947.   (multiple-value-bind (preview-time preview-duration)
  1948.                        (get-movie-preview-time my-movie)
  1949.     (let* ((start-frame (time-to-frame my-movie preview-time :frames-per-second frames-per-second))
  1950.            (end-frame (+ start-frame (time-to-frame my-movie preview-duration :frames-per-second frames-per-second))))
  1951.       (values start-frame end-frame))))
  1952.  
  1953. (defmethod set-movie-preview-time-in-frames ((my-movie movie) start-frame end-frame &key (frames-per-second *frames-per-second*))
  1954.   (let* ((preview-time (frame-to-time my-movie start-frame :frames-per-second frames-per-second))
  1955.          (preview-duration (frame-to-time my-movie (- end-frame start-frame) :frames-per-second frames-per-second)))
  1956.     (set-movie-preview-time my-movie preview-time preview-duration)))
  1957.  
  1958.  
  1959. ;;;-----------------------------------------------------------------------------
  1960. ;;; 
  1961. ;;; Frame-Based Functions For Generating QuickDraw Pictures From Movies
  1962. ;;; 
  1963. ;;;-----------------------------------------------------------------------------
  1964.  
  1965. (defmethod get-movie-pict-in-frames ((my-movie movie) frame &key (frames-per-second *frames-per-second*))
  1966.   (get-movie-pict my-movie (frame-to-time my-movie frame :frames-per-second frames-per-second)))
  1967.  
  1968.  
  1969. ;;;-----------------------------------------------------------------------------
  1970. ;;; 
  1971. ;;; Frame-Based Functions For Editing Movies
  1972. ;;; 
  1973. ;;;-----------------------------------------------------------------------------
  1974.  
  1975. (defmethod get-movie-selection-in-frames ((my-movie movie) &key (frames-per-second *frames-per-second*))
  1976.   (multiple-value-bind (start-time duration)
  1977.                        (get-movie-selection my-movie)
  1978.     (let* ((start-frame (time-to-frame my-movie start-time :frames-per-second frames-per-second))
  1979.            (end-frame (+ start-frame (time-to-frame my-movie duration :frames-per-second frames-per-second))))
  1980.       (values start-frame end-frame))))
  1981.  
  1982. (defmethod set-movie-selection-in-frames ((my-movie movie)
  1983.                                           start-frame
  1984.                                           end-frame
  1985.                                           &key (frames-per-second *frames-per-second*))
  1986.   (let* ((start-time (frame-to-time my-movie start-frame :frames-per-second frames-per-second))
  1987.          (duration (frame-to-time my-movie (- end-frame start-frame) :frames-per-second frames-per-second)))
  1988.     (set-movie-selection my-movie start-time duration)))
  1989.  
  1990.  
  1991. (defmethod paste-specified-selection-in-frames ((source-movie movie)
  1992.                                                 source-start-frame
  1993.                                                 source-end-frame
  1994.                                                 (destination-movie movie)
  1995.                                                 &key (frames-per-second *frames-per-second*))
  1996.   (set-movie-selection-in-frames source-movie
  1997.                                  source-start-frame
  1998.                                  source-end-frame
  1999.                                  :frames-per-second frames-per-second)
  2000.   (paste-movie-selection source-movie
  2001.                          destination-movie))
  2002.  
  2003.  
  2004. ;;;-----------------------------------------------------------------------------
  2005. ;;; 
  2006. ;;; Frame-Based Functions For Low-Level Movie Editing
  2007. ;;; 
  2008. ;;;-----------------------------------------------------------------------------
  2009.  
  2010. (defmethod delete-movie-segment-in-frames ((my-movie movie)
  2011.                                            start-frame
  2012.                                            end-frame
  2013.                                            &key (frames-per-second *frames-per-second*))
  2014.   (let* ((start-time (frame-to-time my-movie start-frame :frames-per-second frames-per-second))
  2015.          (duration (frame-to-time my-movie (- end-frame start-frame) :frames-per-second frames-per-second)))
  2016.     (delete-movie-segment my-movie start-time duration)))
  2017.  
  2018. (defmethod insert-empty-movie-segment-in-frames ((my-movie movie)
  2019.                                        start-frame
  2020.                                        end-frame
  2021.                                        &key (frames-per-second *frames-per-second*))
  2022.   "Inserts empty space into a movie -- but cannot do this at the end of a movie"
  2023.   (let* ((start-time (frame-to-time my-movie start-frame :frames-per-second frames-per-second))
  2024.          (duration (frame-to-time my-movie (- end-frame start-frame) :frames-per-second frames-per-second)))
  2025.     (insert-empty-movie-segment my-movie start-time duration)))
  2026.  
  2027.  
  2028. (defmethod insert-movie-segment-in-frames ((my-source-movie movie) (my-destination-movie movie) 
  2029.                                            &key
  2030.                                            source-movie-segment-start-frame
  2031.                                            source-movie-segment-end-frame 
  2032.                                            destination-movie-insert-start-frame
  2033.                                            (frames-per-second *frames-per-second*))
  2034.   (let* ((source-in-time-value (frame-to-time my-source-movie source-movie-segment-start-frame :frames-per-second frames-per-second))
  2035.          (source-duration (frame-to-time my-source-movie (- source-movie-segment-end-frame source-movie-segment-start-frame) :frames-per-second frames-per-second))
  2036.          (destination-in-time-value (frame-to-time my-destination-movie destination-movie-insert-start-frame :frames-per-second frames-per-second)))
  2037.     (insert-movie-segment my-source-movie my-destination-movie 
  2038.                           :source-movie-segment-start-time source-in-time-value
  2039.                           :source-movie-segment-duration source-duration
  2040.                           :destination-movie-insert-start-time destination-in-time-value)))
  2041.  
  2042. (defmethod scale-movie-segment-in-frames ((my-movie movie) 
  2043.                                           start-frame
  2044.                                           old-end-frame 
  2045.                                           new-end-frame
  2046.                                           &key (frames-per-second *frames-per-second*))
  2047.   (let* ((start-time (frame-to-time my-movie start-frame :frames-per-second frames-per-second))
  2048.          (old-duration (frame-to-time my-movie (- old-end-frame start-frame) :frames-per-second frames-per-second))
  2049.          (new-duration (frame-to-time my-movie (- new-end-frame start-frame) :frames-per-second frames-per-second)))
  2050.     (scale-movie-segment my-movie start-time old-duration new-duration)))
  2051.  
  2052.  
  2053. ;;;-----------------------------------------------------------------------------
  2054. ;;; 
  2055. ;;; Frame-Based Functions For Working With Movie Time
  2056. ;;; 
  2057. ;;;-----------------------------------------------------------------------------
  2058.  
  2059. (defmethod get-movie-duration-in-frames ((my-movie movie) &key (frames-per-second *frames-per-second*))
  2060.   (time-to-frame my-movie (get-movie-duration my-movie) :frames-per-second frames-per-second))
  2061.  
  2062. (defmethod get-movie-time-in-frames ((my-movie movie) &key (frames-per-second *frames-per-second*))
  2063.   (time-to-frame my-movie (get-movie-time my-movie) :frames-per-second frames-per-second))
  2064.  
  2065. (defmethod get-movie-frame ((my-movie movie) &key (frames-per-second *frames-per-second*))
  2066.   (get-movie-time-in-frames my-movie :frames-per-second frames-per-second))
  2067.  
  2068. (defmethod set-movie-time-in-frames ((my-movie movie) frame &optional time-scale &key (frames-per-second *frames-per-second*))
  2069.   (let* ((time-scale (if time-scale time-scale (get-movie-time-scale my-movie)))
  2070.          (time (frame-to-time my-movie frame :frames-per-second frames-per-second)))
  2071.     (set-movie-time my-movie time time-scale)))
  2072.  
  2073. (defmethod set-movie-frame ((my-movie movie) frame &key (frames-per-second *frames-per-second*))
  2074.   (set-movie-time-value-in-frames my-movie frame :frames-per-second frames-per-second))
  2075.  
  2076. (defmethod set-movie-time-value-in-frames ((my-movie movie) frame &key (frames-per-second *frames-per-second*))
  2077.   (set-movie-time-value my-movie (frame-to-time my-movie frame :frames-per-second frames-per-second)))
  2078.  
  2079.  
  2080.  
  2081. ;;;-----------------------------------------------------------------------------
  2082. ;;; 
  2083. ;;; TEST CODE
  2084. ;;; 
  2085. ;;;-----------------------------------------------------------------------------
  2086.  
  2087. (defun movie-test (&key (show-controller t))
  2088.   (make-instance 'movie-window
  2089.     :movie (make-instance 'movie)
  2090.     :show-controller show-controller))
  2091.  
  2092. ;;; Show multiple movies.  Use the interface designer to move and scale...
  2093. (defun clip-library (paths)
  2094.   (let ((window (make-instance 'dialog
  2095.                   :window-title "Clip Library"
  2096.                   :view-size #@(400 400))))
  2097.     (dolist (path (directory paths))
  2098.       (make-instance 'movie-dialog-item
  2099.         :movie (make-instance 'movie :file path)
  2100.         :view-container window))))
  2101.  
  2102. (defun play-all (clip-library-window)
  2103.   (dolist (v (coerce (view-subviews clip-library-window) 'list))
  2104.     (when (typep v 'movie-view)
  2105.       (rewind-movie (slot-value v 'movie))
  2106.       (play-movie (slot-value v 'movie)))))
  2107.  
  2108.  
  2109. ;;;-----------------------------------------------------------------------------
  2110. ;;; 
  2111. ;;; START QUICKTIME
  2112. ;;; 
  2113. ;;;-----------------------------------------------------------------------------
  2114.  
  2115. (initialize-quicktime)
  2116.  
  2117.  
  2118.  
  2119.  
  2120. ;;;-----------------------------------------------------------------------------
  2121. ;;; 
  2122. ;;; Debugging notes
  2123. ;;; 
  2124. ;;;-----------------------------------------------------------------------------
  2125.  
  2126. ;; New and changed functions from qt-objects.lisp v2.0 (Wednesday, 12/9/92)
  2127. ;; Mods by Michael Korcuska (12/30/92)
  2128. ;;
  2129. ;; New Functions:
  2130. ;;   
  2131. ;;    create-movie-file-from-fsspec
  2132. ;;    get-movie-from-fsspec
  2133. ;;    new-movie-path
  2134. ;;    add-movie-resource-to-fsspec
  2135. ;;    remove-movie-resource-from-fsspec
  2136. ;;    update-movie-resource-fsspec
  2137. ;;    flatten-movie-fsspec
  2138. ;;    fsspec-exists-p
  2139. ;;    valid-fsspec-p
  2140. ;;
  2141. ;; The changed functions are essentially those which created fsSpec records
  2142. ;; and their callers.  It is now the responsibility of the caller to allocate
  2143. ;; the fsSpec (with rlet in all cases)
  2144. ;;
  2145. ;; I've minimally tested all of these functions using movie-test, my own
  2146. ;; application and individual calls to the resource functions.
  2147. ;;
  2148. ;; Comments:
  2149. ;;   I think there's a problem with the class definitions, but I'm not sure.
  2150. ;; When you create a movie from a file, the file information is no longer
  2151. ;; important.  I don't think, therefore, that the file/refnum/id should be
  2152. ;; part of the movie class.  Instead there should be a class movie-file with
  2153. ;; that information.  This has many implications and would be a major rewrite,
  2154. ;; which I certainly don't have time to do.
  2155. ;;   I noticed the problem when working with the resource functions, which allow
  2156. ;; me to create a new movie file and add an existing movie to it.  When I do this, 
  2157. ;; the file info associated with the existing movie gets set to the new file and
  2158. ;; I have no way of accessing the old file info, which means I can't close it.
  2159. ;; I don't know if there is a quick fix to this except to comment the resource
  2160. ;; code in the distribution.  Let me know what you think.
  2161. ;;
  2162. ;;  Cheers,    Michael
  2163. ;;
  2164.  
  2165.  
  2166.  
  2167.  
  2168.